From 98e903e0a0db5e0ab7be46010a0bf7c282b5da15 Mon Sep 17 00:00:00 2001
From: tientq64
Date: Fri, 31 Jan 2025 17:29:52 +0700
Subject: [PATCH 01/19] fix: Incorrectly removed ad elements, attempt to fix
issue #5
---
scripts/Auto-Skip-YouTube-Ads/script.user.js | 9 +++++----
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 11 ++++++-----
watch.ts | 2 +-
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index 0ebf0e7..0912e44 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.0
+// @version 6.0.1
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -140,9 +140,9 @@ function removeAdElements() {
['#panels', 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]'],
// Sponsored ad video items on home page.
- ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
+ // ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
- ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
+ // ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
@@ -159,7 +159,7 @@ function removeAdElements() {
for (const adSelector of adSelectors) {
const adEl = document.querySelector(adSelector[0])
if (adEl === null) continue
- const neededEl = document.querySelector(adSelector[1])
+ const neededEl = adEl.querySelector(adSelector[1])
if (neededEl === null) continue
adEl.remove()
}
@@ -171,4 +171,5 @@ window.setInterval(skipAd, 500)
window.setInterval(removeAdElements, 1000)
addCss()
+removeAdElements()
skipAd()
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index a58de55..0d73a35 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.0
+// @version 6.0.1
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -157,9 +157,9 @@ function removeAdElements(): void {
['#panels', 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]'],
// Sponsored ad video items on home page.
- ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
+ // ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
- ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
+ // ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
@@ -174,9 +174,9 @@ function removeAdElements(): void {
['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
- const adEl = document.querySelector(adSelector[0])
+ const adEl = document.querySelector(adSelector[0])
if (adEl === null) continue
- const neededEl = document.querySelector(adSelector[1])
+ const neededEl = adEl.querySelector(adSelector[1])
if (neededEl === null) continue
adEl.remove()
}
@@ -188,4 +188,5 @@ window.setInterval(skipAd, 500)
window.setInterval(removeAdElements, 1000)
addCss()
+removeAdElements()
skipAd()
diff --git a/watch.ts b/watch.ts
index 0d9678e..bde981c 100644
--- a/watch.ts
+++ b/watch.ts
@@ -17,7 +17,7 @@ async function handleWatch(path: string, stat: Stats): Promise {
const dirPath: string = dirname(path).replace(/\\/g, '/')
const code: string = readFileSync(path, 'utf-8')
- const matches = code.match(/\/\/ ==UserScript==\n.+?\n\/\/ ==\/UserScript==/s)
+ const matches = code.match(/\/\/ ==UserScript==\n.+?\n\/\/ ==\/UserScript==/su)
if (matches === null) return
const meta: string = matches[0]
From 681c64b3b0914ce4b45fed399768392ffa06d25e Mon Sep 17 00:00:00 2001
From: tientq64
Date: Sat, 1 Feb 2025 10:21:29 +0700
Subject: [PATCH 02/19] docs: Tetr-io Improvements
---
scripts/Tetr-io-Improvements/README.md | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 scripts/Tetr-io-Improvements/README.md
diff --git a/scripts/Tetr-io-Improvements/README.md b/scripts/Tetr-io-Improvements/README.md
new file mode 100644
index 0000000..dfba14b
--- /dev/null
+++ b/scripts/Tetr-io-Improvements/README.md
@@ -0,0 +1,14 @@
+# Tetr.io Improvements
+
+## Introducion
+
+This userscript makes your [tetr.io][1] playing experience better.
+
+## Features
+
+- Remove smooth motion effects, making navigation faster.
+- Remove ads.
+- Press the `Home` key each time to automatically press the login button, enter Tetra League, start finding matches.
+- Press the `End` key to press the next button when the match ends.
+
+[1]: https://tetr.io
From 4d3988451d845dd3314522b6ec6131221f8e5f2f Mon Sep 17 00:00:00 2001
From: tientq64
Date: Sun, 2 Feb 2025 07:41:28 +0700
Subject: [PATCH 03/19] improvement: Disable some unnecessary CSS
---
scripts/Auto-Skip-YouTube-Ads/README.md | 4 ++++
scripts/Auto-Skip-YouTube-Ads/script.user.js | 22 +++++++++++---------
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 22 +++++++++++---------
3 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/scripts/Auto-Skip-YouTube-Ads/README.md b/scripts/Auto-Skip-YouTube-Ads/README.md
index ec84c6f..bbb4e43 100644
--- a/scripts/Auto-Skip-YouTube-Ads/README.md
+++ b/scripts/Auto-Skip-YouTube-Ads/README.md
@@ -8,6 +8,10 @@ Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát h
## 📑 Changelog
+### 6.0.2 - 2025-02-02
+
+- Disable some unnecessary CSS.
+
### 6.0.0 - 2025-01-29
_Happy Lunar New Year!_
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index 0912e44..e6881c9 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.1
+// @version 6.0.2
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -45,8 +45,8 @@
// ==/UserScript==
function skipAd() {
- const isYouTubeShort = checkIsYouTubeShort()
- if (isYouTubeShort) return
+ const isYouTubeShorts = checkIsYouTubeShorts()
+ if (isYouTubeShorts) return
const hasAd = checkHasAd()
if (!hasAd) return
@@ -77,7 +77,7 @@ function checkHasAd() {
return false
}
-function checkIsYouTubeShort() {
+function checkIsYouTubeShorts() {
return location.pathname.startsWith('/shorts/')
}
@@ -107,8 +107,10 @@ function addCss() {
// Masthead ad on home page.
'#masthead-ad',
- 'ytd-ad-slot-renderer',
- '.ytp-suggested-action',
+ // Sponsored ad video items on home page.
+ // 'ytd-ad-slot-renderer',
+
+ // '.ytp-suggested-action',
'.yt-mealbar-promo-renderer',
// Featured product ad banner at the bottom left of the video.
@@ -145,16 +147,16 @@ function removeAdElements() {
// ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
- ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
+ ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
// Ad blocker warning dialog.
- ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
+ // ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
// Survey dialog on home page, located at bottom right.
- ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
+ // ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
// Survey to rate suggested content, located at bottom right.
- ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
+ // ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
const adEl = document.querySelector(adSelector[0])
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index 0d73a35..7c996df 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.1
+// @version 6.0.2
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -62,8 +62,8 @@ interface YouTubeVideoData {
}
function skipAd(): void {
- const isYouTubeShort: boolean = checkIsYouTubeShort()
- if (isYouTubeShort) return
+ const isYouTubeShorts: boolean = checkIsYouTubeShorts()
+ if (isYouTubeShorts) return
const hasAd: boolean = checkHasAd()
if (!hasAd) return
@@ -94,7 +94,7 @@ function checkHasAd(): boolean {
return false
}
-function checkIsYouTubeShort(): boolean {
+function checkIsYouTubeShorts(): boolean {
return location.pathname.startsWith('/shorts/')
}
@@ -124,8 +124,10 @@ function addCss(): void {
// Masthead ad on home page.
'#masthead-ad',
- 'ytd-ad-slot-renderer',
- '.ytp-suggested-action',
+ // Sponsored ad video items on home page.
+ // 'ytd-ad-slot-renderer',
+
+ // '.ytp-suggested-action',
'.yt-mealbar-promo-renderer',
// Featured product ad banner at the bottom left of the video.
@@ -162,16 +164,16 @@ function removeAdElements(): void {
// ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
- ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
+ ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
// Ad blocker warning dialog.
- ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
+ // ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
// Survey dialog on home page, located at bottom right.
- ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
+ // ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
// Survey to rate suggested content, located at bottom right.
- ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
+ // ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
const adEl = document.querySelector(adSelector[0])
From d4d67abc07e01dc35b2ec327195566e520706c61 Mon Sep 17 00:00:00 2001
From: tientq64
Date: Mon, 10 Feb 2025 20:32:58 +0700
Subject: [PATCH 04/19] Remove `ad-showing` class when there is an ad
---
scripts/Auto-Skip-YouTube-Ads/script.user.js | 19 +++++++--------
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 25 ++++++++++----------
2 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index e6881c9..b47c3de 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.2
+// @version 6.0.3
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -48,12 +48,14 @@ function skipAd() {
const isYouTubeShorts = checkIsYouTubeShorts()
if (isYouTubeShorts) return
- const hasAd = checkHasAd()
- if (!hasAd) return
+ const ad = getInterruptiveAd()
+ if (ad === null) return
const player = getYouTubePlayer()
if (player === null) return
+ ad.classList.remove('ad-showing')
+
const videoData = player.getVideoData()
const videoId = videoData.video_id
const startTime = Math.floor(player.getCurrentTime())
@@ -62,19 +64,16 @@ function skipAd() {
console.log('Ad skipped!', videoId, startTime, videoData.title)
}
-/**
- * Check if there are any ads interrupting the video.
- */
-function checkHasAd() {
+function getInterruptiveAd() {
// This element appears when a video ad appears.
const adShowing = document.querySelector('.ad-showing')
- if (adShowing !== null) return true
+ if (adShowing !== null) return adShowing
// Timed pie countdown ad.
const pieCountdown = document.querySelector('.ytp-ad-timed-pie-countdown-container')
- if (pieCountdown !== null) return true
+ if (pieCountdown !== null) return pieCountdown
- return false
+ return null
}
function checkIsYouTubeShorts() {
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index 7c996df..b934c94 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.2
+// @version 6.0.3
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -65,12 +65,14 @@ function skipAd(): void {
const isYouTubeShorts: boolean = checkIsYouTubeShorts()
if (isYouTubeShorts) return
- const hasAd: boolean = checkHasAd()
- if (!hasAd) return
+ const ad: HTMLElement | null = getInterruptiveAd()
+ if (ad === null) return
const player: YouTubePlayer | null = getYouTubePlayer()
if (player === null) return
+ ad.classList.remove('ad-showing')
+
const videoData: YouTubeVideoData = player.getVideoData()
const videoId: string = videoData.video_id
const startTime: number = Math.floor(player.getCurrentTime())
@@ -79,19 +81,18 @@ function skipAd(): void {
console.log('Ad skipped!', videoId, startTime, videoData.title)
}
-/**
- * Check if there are any ads interrupting the video.
- */
-function checkHasAd(): boolean {
+function getInterruptiveAd(): HTMLElement | null {
// This element appears when a video ad appears.
- const adShowing = document.querySelector('.ad-showing')
- if (adShowing !== null) return true
+ const adShowing = document.querySelector('.ad-showing')
+ if (adShowing !== null) return adShowing
// Timed pie countdown ad.
- const pieCountdown = document.querySelector('.ytp-ad-timed-pie-countdown-container')
- if (pieCountdown !== null) return true
+ const pieCountdown = document.querySelector(
+ '.ytp-ad-timed-pie-countdown-container'
+ )
+ if (pieCountdown !== null) return pieCountdown
- return false
+ return null
}
function checkIsYouTubeShorts(): boolean {
From ee1063d9b642f594ed900379352e11196b41408b Mon Sep 17 00:00:00 2001
From: tientq64
Date: Sun, 16 Feb 2025 00:36:29 +0700
Subject: [PATCH 05/19] Version 6 had many bug reports, reverting to the
previous version 5 (#6).
---
.resources/global.d.ts | 4 +
scripts/Auto-Skip-YouTube-Ads/README.md | 378 ++++++++++---------
scripts/Auto-Skip-YouTube-Ads/script.user.js | 352 +++++++++++++----
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 376 +++++++++++++-----
4 files changed, 757 insertions(+), 353 deletions(-)
diff --git a/.resources/global.d.ts b/.resources/global.d.ts
index 8b51306..f3fbb53 100644
--- a/.resources/global.d.ts
+++ b/.resources/global.d.ts
@@ -53,5 +53,9 @@ interface YtdPlayerElement extends HTMLElement {
loadVideoWithPlayerVars(options: { videoId: string; start?: number }): void
}
+interface YouTubeMoviePlayerElement extends HTMLElement {
+ loadVideoByPlayerVars(options: { videoId: string; start?: number }): void
+}
+
declare type TrustedTypePolicyFactory = import('trusted-types/lib').TrustedTypePolicyFactory
declare const trustedTypes: TrustedTypePolicyFactory
diff --git a/scripts/Auto-Skip-YouTube-Ads/README.md b/scripts/Auto-Skip-YouTube-Ads/README.md
index bbb4e43..27aa020 100644
--- a/scripts/Auto-Skip-YouTube-Ads/README.md
+++ b/scripts/Auto-Skip-YouTube-Ads/README.md
@@ -1,186 +1,192 @@
-## 📰 Introduction
-
-Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
-
-立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
-
-Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát hiện bởi cảnh báo trình chặn quảng cáo của YouTube.
-
-## 📑 Changelog
-
-### 6.0.2 - 2025-02-02
-
-- Disable some unnecessary CSS.
-
-### 6.0.0 - 2025-01-29
-
-_Happy Lunar New Year!_
-
-- Completely rewritten way to skip ads, more efficient, not detected by YouTube ad blocker warning.
-- New way to skip ads is temporarily not working on YouTube Music.
-
-### 5.3.0 - 2025-01-23
-
-- Supports older browser versions.
-
-### 5.2.0 - 2025-01-21
-
-- Support for **YouTube mobile** version 🎉
-- Revisit fix for issue [#2]: Fully resolved the problem where videos couldn't be paused on mobile. The previous fix was incomplete.
-
-### 5.1.3 - 2025-01-18
-
-- Fix ad skipping issue.
-
-### 5.1.2 - 2025-01-17
-
-- Fix issue [#2] where video can't be paused on mobile.
-
-### 5.1.1 - 2024-12-27
-
-- Hide the survey to rate suggested content, located at bottom right.
-
-### 5.1.0 - 2024-12-26
-
-- Skip pie countdown ads 🎉
-
-### 5.0.0 - 2024-12-25
-
-_Merry Christmas!_
-
-- **No need to reload the page** when there is no way to skip the ad anymore 🤯
-- Configuration removed, no longer needed.
-
-### 4.8.2 - 2024-12-21
-
-- Fix timestamp loss when reloading.
-
-### 4.8.1 - 2024-12-03
-
-- Hide survey dialog on home page.
-
-### 4.8.0 - 2024-11-26
-
-- The current video's timestamp will be preserved when the page is reloaded ([#267857]).
-
-### 4.7.4 - 2024-11-20
-
-- Improved ad skipping.
-
-### 4.7.0 - 2024-10-26
-
-- Add option "Don't reload while the user is busy" in Tampermonkey's menu to avoid reloading page when user is busy doing something, like reading comments, entering text. Enabled by default.
-
-### 4.6.2 - 2024-10-13
-
-- Improve hiding of ad banners.
-
-### 4.6.0 - 2024-10-07
-
-- Support skipping ads on **YouTube Music** (PR [#1]).
-
-### 4.5.2 - 2024-09-30
-
-- Fix Shorts reload infinitely ([#258626], [#259545], [#261679]).
-
-### 4.5.0 - 2024-09-26
-
-- Add option to enable/disable "Reload the page when there is no other way to skip ads" feature in Tampermonkey's menu. Enabled by default.\
- ![Screenshot-001]
-
-### 4.4.0 - 2024-08-30
-
-- Automatically reload web page when ad blocker warnings appear.
-
-### 4.3.13 - 2024-08-26
-
-- Fixed bug where video could not be paused using pause/play key on keyboard or media controls ([#257424]).
-- Improve the performance.
-
-### 4.3.9 - 2024-08-21
-
-- Fix `@match` invalid syntax ([#256841]).
-
-### 4.3.8 - 2024-08-20
-
-- Fix the issue of removing ad videos in Shorts.
-
-### 4.3.6 - 2024-08-07
-
-- Fix bug where video rewinds a segment after skipping an ad ([#254113]).
-
-### 4.3.4 - 2024-08-02
-
-- Improve the performance.
-
-### 4.2.1 - 2024-07-30
-
-- Fixed video automatically replay when ended.
-
-### 4.2.0 - 2024-07-30
-
-- Videos will now no longer occasionally pause due to ad blocker use.
-- Faster ad video skipping speed.
-
-### 4.1.0 - 2024-07-10
-
-- No need to reload the page when the ad blocker warning dialog appears.
-
-### 4.0.0 - 2024-07-09
-
-- The page will now reload if an ad blocker warning dialog appears. Because YouTube now pauses the video at first if an ad blocker is detected.
-- Write to the Console every time skip an ad video, etc. Purpose to help debug. To open the Console, press `Ctrl+Shift+J`.
-
-### 3.1.2 - 2024-07-06
-
-- Playing video after clicking dismiss the ad blocker warning popup.
-
-### 3.1.1 - 2024-07-04
-
-- Add a few CSS that hides the ads.
-
-### 3.1.0 - 2024-07-02
-
-- Skip ads faster when the tab is active.
-- Fixed bug when set time to end of ad video without the video duration being available.
-- Change icon.
-
-### 3.0.2 - 2024-06-28
-
-- Rewriting to only use `setInterval` simplifies things, and fix some bugs.
-
-### 2.1.3 - 2024-06-21
-
-- Fix `popupContainer` not found error.
-
-### 2.1.0 - 2024-06-20
-
-- Auto close YouTube's ad blocker warning popup.
-
-### 2.0.1 - 2024-06-19
-
-- Improved skip ad button detection.
-- Fall back to `setInterval` when `MutationObserver` is not supported.
-
-### 2.0.0 - 2024-06-18
-
-- Rewrite the entire code, use `MutationObserver` instead of `setInterval`.
-
-### 1.0.0 - 2024-06-17
-
-- Stable release.
-
-## 💳 Credits
-
-Youtube icons created by Ruslan Babkin - Flaticon.
-
-[#2]: https://github.com/tientq64/userscripts/issues/2
-[#267857]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/267857
-[#258626]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/258626
-[#259545]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/259545
-[#261679]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/261679
-[#257424]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/257424
-[#256841]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/256841
-[#254113]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/254113
-[#1]: https://github.com/tientq64/userscripts/pull/1
-[Screenshot-001]: https://cdn.jsdelivr.net/gh/tientq64/userscripts/scripts/Auto-Skip-YouTube-Ads/assets/screenshot-001.png
+## 📰 Introduction
+
+Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
+
+立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
+
+Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát hiện bởi cảnh báo trình chặn quảng cáo của YouTube.
+
+## 📑 Changelog
+
+### 7.0.0 - 2025-02-15
+
+- Version 6 had many bug reports, reverting to the previous version 5 ([#6], [#279168]).
+
+### 6.0.2 - 2025-02-02
+
+- Disable some unnecessary CSS.
+
+### 6.0.0 - 2025-01-29
+
+_Happy Lunar New Year!_
+
+- Completely rewritten way to skip ads, more efficient, not detected by YouTube ad blocker warning.
+- New way to skip ads is temporarily not working on YouTube Music.
+
+### 5.3.0 - 2025-01-23
+
+- Supports older browser versions.
+
+### 5.2.0 - 2025-01-21
+
+- Support for **YouTube mobile** version 🎉
+- Revisit fix for issue [#2]: Fully resolved the problem where videos couldn't be paused on mobile. The previous fix was incomplete.
+
+### 5.1.3 - 2025-01-18
+
+- Fix ad skipping issue.
+
+### 5.1.2 - 2025-01-17
+
+- Fix issue [#2] where video can't be paused on mobile.
+
+### 5.1.1 - 2024-12-27
+
+- Hide the survey to rate suggested content, located at bottom right.
+
+### 5.1.0 - 2024-12-26
+
+- Skip pie countdown ads 🎉
+
+### 5.0.0 - 2024-12-25
+
+_Merry Christmas!_
+
+- **No need to reload the page** when there is no way to skip the ad anymore 🤯
+- Configuration removed, no longer needed.
+
+### 4.8.2 - 2024-12-21
+
+- Fix timestamp loss when reloading.
+
+### 4.8.1 - 2024-12-03
+
+- Hide survey dialog on home page.
+
+### 4.8.0 - 2024-11-26
+
+- The current video's timestamp will be preserved when the page is reloaded ([#267857]).
+
+### 4.7.4 - 2024-11-20
+
+- Improved ad skipping.
+
+### 4.7.0 - 2024-10-26
+
+- Add option "Don't reload while the user is busy" in Tampermonkey's menu to avoid reloading page when user is busy doing something, like reading comments, entering text. Enabled by default.
+
+### 4.6.2 - 2024-10-13
+
+- Improve hiding of ad banners.
+
+### 4.6.0 - 2024-10-07
+
+- Support skipping ads on **YouTube Music** (PR [#1]).
+
+### 4.5.2 - 2024-09-30
+
+- Fix Shorts reload infinitely ([#258626], [#259545], [#261679]).
+
+### 4.5.0 - 2024-09-26
+
+- Add option to enable/disable "Reload the page when there is no other way to skip ads" feature in Tampermonkey's menu. Enabled by default.\
+ ![Screenshot-001]
+
+### 4.4.0 - 2024-08-30
+
+- Automatically reload web page when ad blocker warnings appear.
+
+### 4.3.13 - 2024-08-26
+
+- Fixed bug where video could not be paused using pause/play key on keyboard or media controls ([#257424]).
+- Improve the performance.
+
+### 4.3.9 - 2024-08-21
+
+- Fix `@match` invalid syntax ([#256841]).
+
+### 4.3.8 - 2024-08-20
+
+- Fix the issue of removing ad videos in Shorts.
+
+### 4.3.6 - 2024-08-07
+
+- Fix bug where video rewinds a segment after skipping an ad ([#254113]).
+
+### 4.3.4 - 2024-08-02
+
+- Improve the performance.
+
+### 4.2.1 - 2024-07-30
+
+- Fixed video automatically replay when ended.
+
+### 4.2.0 - 2024-07-30
+
+- Videos will now no longer occasionally pause due to ad blocker use.
+- Faster ad video skipping speed.
+
+### 4.1.0 - 2024-07-10
+
+- No need to reload the page when the ad blocker warning dialog appears.
+
+### 4.0.0 - 2024-07-09
+
+- The page will now reload if an ad blocker warning dialog appears. Because YouTube now pauses the video at first if an ad blocker is detected.
+- Write to the Console every time skip an ad video, etc. Purpose to help debug. To open the Console, press `Ctrl+Shift+J`.
+
+### 3.1.2 - 2024-07-06
+
+- Playing video after clicking dismiss the ad blocker warning popup.
+
+### 3.1.1 - 2024-07-04
+
+- Add a few CSS that hides the ads.
+
+### 3.1.0 - 2024-07-02
+
+- Skip ads faster when the tab is active.
+- Fixed bug when set time to end of ad video without the video duration being available.
+- Change icon.
+
+### 3.0.2 - 2024-06-28
+
+- Rewriting to only use `setInterval` simplifies things, and fix some bugs.
+
+### 2.1.3 - 2024-06-21
+
+- Fix `popupContainer` not found error.
+
+### 2.1.0 - 2024-06-20
+
+- Auto close YouTube's ad blocker warning popup.
+
+### 2.0.1 - 2024-06-19
+
+- Improved skip ad button detection.
+- Fall back to `setInterval` when `MutationObserver` is not supported.
+
+### 2.0.0 - 2024-06-18
+
+- Rewrite the entire code, use `MutationObserver` instead of `setInterval`.
+
+### 1.0.0 - 2024-06-17
+
+- Stable release.
+
+## 💳 Credits
+
+Youtube icons created by Ruslan Babkin - Flaticon.
+
+[#6]: https://github.com/tientq64/userscripts/issues/6
+[#2]: https://github.com/tientq64/userscripts/issues/2
+[#1]: https://github.com/tientq64/userscripts/pull/1
+[#279168]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/279168
+[#267857]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/267857
+[#261679]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/261679
+[#259545]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/259545
+[#258626]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/258626
+[#257424]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/257424
+[#256841]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/256841
+[#254113]: https://greasyfork.org/scripts/498197-auto-skip-youtube-ads/discussions/254113
+[Screenshot-001]: https://cdn.jsdelivr.net/gh/tientq64/userscripts/scripts/Auto-Skip-YouTube-Ads/assets/screenshot-001.png
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index b47c3de..feebd61 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -1,38 +1,35 @@
// ==UserScript==
// @name Auto Skip YouTube Ads
-// @name:ar تخطي إعلانات YouTube تلقائيًا
+// @name:ar التخطي التلقائي لإعلانات YouTube
// @name:es Saltar Automáticamente Anuncios De YouTube
-// @name:fr Ignorer Automatiquement Les Publicités YouTube
// @name:hi YouTube विज्ञापन स्वचालित रूप से छोड़ें
// @name:id Lewati Otomatis Iklan YouTube
// @name:ja YouTube 広告を自動スキップ
// @name:ko YouTube 광고 자동 건너뛰기
-// @name:nl YouTube-Advertenties Automatisch Overslaan
// @name:pt-BR Pular Automaticamente Anúncios Do YouTube
// @name:ru Автоматический Пропуск Рекламы На YouTube
// @name:vi Tự Động Bỏ Qua Quảng Cáo YouTube
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.3
-// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
-// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
-// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
-// @description:fr Ignorez automatiquement et instantanément les publicités YouTube. Non détecté par les avertissements du bloqueur de publicités YouTube.
-// @description:hi YouTube विज्ञापनों को स्वचालित रूप से तुरंत छोड़ दें। YouTube विज्ञापन अवरोधक चेतावनियों द्वारा पता नहीं लगाया गया।
-// @description:id Lewati iklan YouTube secara otomatis secara instan. Tidak terdeteksi oleh peringatan pemblokir iklan YouTube.
-// @description:ja YouTube 広告を即座に自動的にスキップします。YouTube 広告ブロッカーの警告には検出されません。
-// @description:ko YouTube 광고를 즉시 자동으로 건너뜁니다. YouTube 광고 차단 경고에 감지되지 않습니다.
-// @description:nl Sla YouTube-advertenties direct automatisch over. Ongemerkt door YouTube-adblockerwaarschuwingen.
-// @description:pt-BR Pule anúncios do YouTube instantaneamente. Não detectado pelos avisos do bloqueador de anúncios do YouTube.
-// @description:ru Автоматически пропускать рекламу YouTube мгновенно. Не обнаруживается предупреждениями блокировщиков рекламы YouTube.
-// @description:vi Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát hiện bởi cảnh báo trình chặn quảng cáo của YouTube.
-// @description:zh-CN 立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
-// @description:zh-TW 立即自動跳過 YouTube 廣告。 YouTube 廣告攔截器警告未被偵測到。
+// @version 7.0.0
+// @description Automatically skip YouTube ads almost instantly. Remove the ad blocker warning pop-up.
+// @description:ar تخطي إعلانات YouTube تلقائيًا في الحال. إزالة النافذة المنبثقة لتحذير مانع الإعلانات.
+// @description:es Omite automáticamente los anuncios de YouTube casi al instante. Elimina la ventana emergente de advertencia del bloqueador de anuncios.
+// @description:hi YouTube विज्ञापनों को लगभग तुरंत ही स्वचालित रूप से छोड़ दें। विज्ञापन अवरोधक चेतावनी पॉप-अप हटाएँ।
+// @description:id Lewati iklan YouTube secara otomatis hampir seketika. Hapus pop-up peringatan pemblokir iklan.
+// @description:ja YouTube 広告をほぼ瞬時に自動的にスキップします。広告ブロッカーの警告ポップアップを削除します。
+// @description:ko YouTube 광고를 거의 즉시 자동으로 건너뜁니다. 광고 차단 경고 팝업을 제거합니다.
+// @description:pt-BR Pule automaticamente os anúncios do YouTube quase instantaneamente. Remova o pop-up de aviso do bloqueador de anúncios.
+// @description:ru Автоматически пропускайте рекламу YouTube почти мгновенно. Уберите всплывающее предупреждение о блокировщике рекламы.
+// @description:vi Tự động bỏ qua quảng cáo YouTube gần như ngay lập tức. Loại bỏ cửa sổ bật lên cảnh báo trình chặn quảng cáo.
+// @description:zh-CN 几乎立即自动跳过 YouTube 广告。删除广告拦截器警告弹出窗口。
+// @description:zh-TW 幾乎立即自動跳過 YouTube 廣告。刪除廣告攔截器警告彈出視窗。
// @author tientq64
// @icon https://cdn-icons-png.flaticon.com/64/2504/2504965.png
// @match https://www.youtube.com/*
// @match https://m.youtube.com/*
+// @match https://music.youtube.com/*
// @grant none
// @license MIT
// @compatible firefox
@@ -44,95 +41,253 @@
// @homepage https://github.com/tientq64/userscripts/tree/main/scripts/Auto-Skip-YouTube-Ads
// ==/UserScript==
+/**
+ * Skip ads. Remove ad elements.
+ */
function skipAd() {
- const isYouTubeShorts = checkIsYouTubeShorts()
- if (isYouTubeShorts) return
+ removeAdElements()
- const ad = getInterruptiveAd()
- if (ad === null) return
+ video = null
+ fineScrubber = document.querySelector('.ytp-fine-scrubbing')
- const player = getYouTubePlayer()
- if (player === null) return
+ // Check if the current URL is a YouTube Shorts URL and exit the function if true.
+ if (window.location.pathname.startsWith('/shorts/')) return
- ad.classList.remove('ad-showing')
+ const moviePlayer = document.querySelector('#movie_player')
- const videoData = player.getVideoData()
- const videoId = videoData.video_id
- const startTime = Math.floor(player.getCurrentTime())
- player.loadVideoById(videoId, startTime)
+ if (moviePlayer) {
+ hasAd = moviePlayer.classList.contains('ad-showing')
+ video = moviePlayer.querySelector('video.html5-main-video')
+ }
- console.log('Ad skipped!', videoId, startTime, videoData.title)
-}
+ if (hasAd) {
+ const skipButton = document.querySelector(`
+ .ytp-skip-ad-button,
+ .ytp-ad-skip-button,
+ .ytp-ad-skip-button-modern,
+ .ytp-ad-survey-answer-button
+ `)
+ // Click the skip ad button if available.
+ if (skipButton) {
+ skipButton.click()
+ skipButton.remove()
+ }
+ // Otherwise, fast forward to the end of the ad video.
+ // Use `9999` instead of `video.duration` to avoid errors when `duration` is not a number.
+ else if (video && video.src) {
+ video.currentTime = 9999
+ }
+ }
-function getInterruptiveAd() {
- // This element appears when a video ad appears.
- const adShowing = document.querySelector('.ad-showing')
- if (adShowing !== null) return adShowing
+ if (video) {
+ video.addEventListener('pause', handleVideoPause)
+ video.addEventListener('pointerup', allowPauseVideo)
+ video.addEventListener('timeupdate', handleVideoTimeUpdate)
+ }
// Timed pie countdown ad.
const pieCountdown = document.querySelector('.ytp-ad-timed-pie-countdown-container')
- if (pieCountdown !== null) return pieCountdown
+ if (pieCountdown) {
+ pieCountdown.remove()
+ replaceCurrentVideo()
+ }
+
+ // Handle when ad blocker warning appears inside video player.
+ const adBlockerWarningInner = document.querySelector(
+ '.yt-playability-error-supported-renderers'
+ )
+ if (adBlockerWarningInner) {
+ adBlockerWarningInner.remove()
+ document.addEventListener('yt-navigate-finish', handleYouTubeNavigateFinish)
+ replaceCurrentVideo()
+ }
+
+ // Video play/pause button.
+ const playButton = document.querySelector(
+ 'button.ytp-play-button, button.player-control-play-pause-icon'
+ )
+ if (playButton) {
+ playButton.addEventListener('click', allowPauseVideo)
+ }
+}
+
+function queryHasSelector(selector, hasSelector, element = document) {
+ const el = element.querySelector(selector)
+ if (el === null) return null
+ const hasEl = el.querySelector(hasSelector)
+ if (hasEl === null) return null
+ return el
+}
+
+function queryHasSelectorAll(selector, hasSelector, element = document) {
+ const els = element.querySelectorAll(selector)
+ const result = []
+ for (const el of els) {
+ const hasEl = el.querySelector(hasSelector)
+ if (hasEl === null) continue
+ result.push(el)
+ }
+ return result
+}
- return null
+function getCurrentVideoId() {
+ const params = new URLSearchParams(location.search)
+ const videoId = params.get('v')
+ return videoId
}
-function checkIsYouTubeShorts() {
- return location.pathname.startsWith('/shorts/')
+/**
+ * Check if the user is focused on the input.
+ */
+function checkEnteringInput() {
+ if (document.activeElement === null) {
+ return false
+ }
+ return document.activeElement.matches('input, textarea, select')
}
/**
- * Finds and returns the current YouTube video player.
- *
- * @returns The current YouTube video player, or `null` if not found.
+ * Temporarily allows the video to be paused, for a short period of time.
*/
-function getYouTubePlayer() {
- let player
- if (isYouTubeMobile) {
- const playerEl = document.querySelector('#movie_player')
- player = playerEl
+function allowPauseVideo() {
+ pausedByUser = true
+ window.clearTimeout(allowPauseVideoTimeoutId)
+ allowPauseVideoTimeoutId = window.setTimeout(disallowPauseVideo, 500)
+}
+
+/**
+ * Pausing the video is not allowed. The purpose is to prevent video from being paused,
+ * against the behavior of pausing video when YouTube ad blocking warning dialog appears.
+ * Unless certain conditions, such as pausing by user, etc.
+ */
+function disallowPauseVideo() {
+ pausedByUser = false
+ window.clearTimeout(allowPauseVideoTimeoutId)
+}
+
+function handleWindowBlur() {
+ isTabBlurred = true
+}
+
+function handleWindowFocus() {
+ isTabBlurred = false
+}
+
+/**
+ * Handle when video is paused. If certain conditions are not met, it will continue
+ * playing. Returning early in this function means the video should be paused as it should
+ * be.
+ */
+function handleVideoPause() {
+ if (isYouTubeMusic) return
+
+ // If it was stopped by the user, it's ok, let the video pause as it should, and exit the function.
+ if (pausedByUser) {
+ disallowPauseVideo()
+ return
+ }
+
+ // The video will pause normally if the tab is not focused. This is to allow for pausing the video via the media controller (of the browser or operating system), etc.
+ // Note: While this also gives YouTube the opportunity to pause videos to annoy users, it's an acceptable trade-off.
+ if (document.hidden) return
+ if (isTabBlurred) return
+
+ if (fineScrubber && fineScrubber.style.display !== 'none') return
+ if (video === null) return
+ if (video.duration - video.currentTime < 0.1) return
+
+ // This is YouTube's disruptive behavior towards users, so the video should continue to play as normal.
+ video.play()
+}
+
+function handleVideoTimeUpdate() {
+ if (hasAd || video === null) return
+ currentVideoTime = video.currentTime
+}
+
+/**
+ * Handle both keyboard press or release events.
+ */
+function handleWindowKeyDownAndKeyUp(event) {
+ if (isYouTubeMusic) return
+ if (checkEnteringInput()) return
+ const code = event.code
+ if (event.type === 'keydown') {
+ if (code === 'KeyK' || code === 'MediaPlayPause') {
+ allowPauseVideo()
+ }
} else {
- const playerEl = document.querySelector('#ytd-player')
- if (playerEl === null) return null
- player = playerEl.getPlayer()
+ if (code === 'Space') {
+ allowPauseVideo()
+ }
+ }
+}
+
+function handleYouTubeNavigateFinish() {
+ currentVideoTime = 0
+ replaceCurrentVideo()
+}
+
+async function replaceCurrentVideo() {
+ const start = Math.floor(currentVideoTime)
+ for (let i = 0; i < 16; i++) {
+ await waitFor(500)
+ const videoId = getCurrentVideoId()
+ if (!videoId || !video || video.src) continue
+ if (isYouTubeMobile) {
+ const player = document.querySelector('#movie_player')
+ if (!player) continue
+ player.loadVideoByPlayerVars({ videoId, start })
+ } else {
+ const player = document.querySelector('#ytd-player')
+ if (!player) continue
+ player.loadVideoWithPlayerVars({ videoId, start })
+ }
}
- return player
}
+function waitFor(millis) {
+ return new Promise((resolve) => {
+ window.setTimeout(resolve, millis)
+ })
+}
+
+/**
+ * Add CSS hides some ad elements on the page.
+ */
function addCss() {
- const adsSelectors = [
+ const hideCssSelector = [
// Ad banner in the upper right corner, above the video playlist.
'#player-ads',
// Masthead ad on home page.
'#masthead-ad',
- // Sponsored ad video items on home page.
- // 'ytd-ad-slot-renderer',
+ 'ytd-ad-slot-renderer',
- // '.ytp-suggested-action',
- '.yt-mealbar-promo-renderer',
+ // Ad blocker warning inside the player.
+ 'yt-playability-error-supported-renderers#error-screen',
- // Featured product ad banner at the bottom left of the video.
- '.ytp-featured-product',
-
- // Products shelf ad banner below the video description.
- 'ytd-merch-shelf-renderer',
+ '.ytp-suggested-action',
+ '.yt-mealbar-promo-renderer',
// YouTube Music Premium trial promotion dialog, bottom left corner.
'ytmusic-mealbar-promo-renderer',
// YouTube Music Premium trial promotion banner on home page.
'ytmusic-statement-banner-renderer'
- ]
- const adsSelector = adsSelectors.join(',')
- const css = `${adsSelector} { display: none !important; }`
+ ].join(',')
+ const css = `
+ #ytd-player { visibility: visible !important; }
+ ${hideCssSelector} { display: none !important; }
+ `
const style = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
}
/**
- * Remove ad elements using JavaScript because these selectors require the use of the CSS
+ * Remove ad elements using javascript because these selectors require the use of the CSS
* `:has` selector which is not supported in older browser versions.
*/
function removeAdElements() {
@@ -140,16 +295,19 @@ function removeAdElements() {
// Ad banner in the upper right corner, above the video playlist.
['#panels', 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]'],
+ // Temporarily comment out this selector to fix issue [#265124](https://greasyfork.org/en/scripts/498197-auto-skip-youtube-ads/discussions/265124).
+ // ['#panels', 'ytd-ads-engagement-panel-content-renderer'],
+
// Sponsored ad video items on home page.
// ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
// ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
- ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
+ ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
// Ad blocker warning dialog.
- // ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
+ ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model']
// Survey dialog on home page, located at bottom right.
// ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
@@ -158,19 +316,63 @@ function removeAdElements() {
// ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
- const adEl = document.querySelector(adSelector[0])
- if (adEl === null) continue
- const neededEl = adEl.querySelector(adSelector[1])
- if (neededEl === null) continue
- adEl.remove()
+ const adEls = queryHasSelectorAll(adSelector[0], adSelector[1])
+ for (const adEl of adEls) {
+ adEl.remove()
+ }
}
}
+/**
+ * Is it YouTube mobile version.
+ */
const isYouTubeMobile = location.hostname === 'm.youtube.com'
-window.setInterval(skipAd, 500)
-window.setInterval(removeAdElements, 1000)
+/**
+ * Is the current page YouTube Music.
+ */
+const isYouTubeMusic = location.hostname === 'music.youtube.com'
+
+/**
+ * Current video element.
+ */
+let video = null
+
+let fineScrubber = null
+let hasAd = false
+let currentVideoTime = 0
+
+/**
+ * Is the video paused by the user, not paused by YouTube's ad blocker warning dialog.
+ */
+let pausedByUser = false
+
+/**
+ * Is the current tab blurred.
+ */
+let isTabBlurred = false
+
+let allowPauseVideoTimeoutId = 0
+
+// Observe DOM changes to detect ads.
+if (window.MutationObserver) {
+ const observer = new MutationObserver(skipAd)
+ observer.observe(document.body, {
+ attributes: true,
+ attributeFilter: ['class', 'src'],
+ childList: true,
+ subtree: true
+ })
+}
+// If DOM observation is not supported. Detect ads every 500ms (2 times per second).
+else {
+ window.setInterval(skipAd, 500)
+}
+
+window.addEventListener('blur', handleWindowBlur)
+window.addEventListener('focus', handleWindowFocus)
+window.addEventListener('keydown', handleWindowKeyDownAndKeyUp)
+window.addEventListener('keyup', handleWindowKeyDownAndKeyUp)
addCss()
-removeAdElements()
skipAd()
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index b934c94..22c5f94 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -1,38 +1,35 @@
// ==UserScript==
// @name Auto Skip YouTube Ads
-// @name:ar تخطي إعلانات YouTube تلقائيًا
+// @name:ar التخطي التلقائي لإعلانات YouTube
// @name:es Saltar Automáticamente Anuncios De YouTube
-// @name:fr Ignorer Automatiquement Les Publicités YouTube
// @name:hi YouTube विज्ञापन स्वचालित रूप से छोड़ें
// @name:id Lewati Otomatis Iklan YouTube
// @name:ja YouTube 広告を自動スキップ
// @name:ko YouTube 광고 자동 건너뛰기
-// @name:nl YouTube-Advertenties Automatisch Overslaan
// @name:pt-BR Pular Automaticamente Anúncios Do YouTube
// @name:ru Автоматический Пропуск Рекламы На YouTube
// @name:vi Tự Động Bỏ Qua Quảng Cáo YouTube
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.3
-// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
-// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
-// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
-// @description:fr Ignorez automatiquement et instantanément les publicités YouTube. Non détecté par les avertissements du bloqueur de publicités YouTube.
-// @description:hi YouTube विज्ञापनों को स्वचालित रूप से तुरंत छोड़ दें। YouTube विज्ञापन अवरोधक चेतावनियों द्वारा पता नहीं लगाया गया।
-// @description:id Lewati iklan YouTube secara otomatis secara instan. Tidak terdeteksi oleh peringatan pemblokir iklan YouTube.
-// @description:ja YouTube 広告を即座に自動的にスキップします。YouTube 広告ブロッカーの警告には検出されません。
-// @description:ko YouTube 광고를 즉시 자동으로 건너뜁니다. YouTube 광고 차단 경고에 감지되지 않습니다.
-// @description:nl Sla YouTube-advertenties direct automatisch over. Ongemerkt door YouTube-adblockerwaarschuwingen.
-// @description:pt-BR Pule anúncios do YouTube instantaneamente. Não detectado pelos avisos do bloqueador de anúncios do YouTube.
-// @description:ru Автоматически пропускать рекламу YouTube мгновенно. Не обнаруживается предупреждениями блокировщиков рекламы YouTube.
-// @description:vi Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát hiện bởi cảnh báo trình chặn quảng cáo của YouTube.
-// @description:zh-CN 立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
-// @description:zh-TW 立即自動跳過 YouTube 廣告。 YouTube 廣告攔截器警告未被偵測到。
+// @version 7.0.0
+// @description Automatically skip YouTube ads almost instantly. Remove the ad blocker warning pop-up.
+// @description:ar تخطي إعلانات YouTube تلقائيًا في الحال. إزالة النافذة المنبثقة لتحذير مانع الإعلانات.
+// @description:es Omite automáticamente los anuncios de YouTube casi al instante. Elimina la ventana emergente de advertencia del bloqueador de anuncios.
+// @description:hi YouTube विज्ञापनों को लगभग तुरंत ही स्वचालित रूप से छोड़ दें। विज्ञापन अवरोधक चेतावनी पॉप-अप हटाएँ।
+// @description:id Lewati iklan YouTube secara otomatis hampir seketika. Hapus pop-up peringatan pemblokir iklan.
+// @description:ja YouTube 広告をほぼ瞬時に自動的にスキップします。広告ブロッカーの警告ポップアップを削除します。
+// @description:ko YouTube 광고를 거의 즉시 자동으로 건너뜁니다. 광고 차단 경고 팝업을 제거합니다.
+// @description:pt-BR Pule automaticamente os anúncios do YouTube quase instantaneamente. Remova o pop-up de aviso do bloqueador de anúncios.
+// @description:ru Автоматически пропускайте рекламу YouTube почти мгновенно. Уберите всплывающее предупреждение о блокировщике рекламы.
+// @description:vi Tự động bỏ qua quảng cáo YouTube gần như ngay lập tức. Loại bỏ cửa sổ bật lên cảnh báo trình chặn quảng cáo.
+// @description:zh-CN 几乎立即自动跳过 YouTube 广告。删除广告拦截器警告弹出窗口。
+// @description:zh-TW 幾乎立即自動跳過 YouTube 廣告。刪除廣告攔截器警告彈出視窗。
// @author tientq64
// @icon https://cdn-icons-png.flaticon.com/64/2504/2504965.png
// @match https://www.youtube.com/*
// @match https://m.youtube.com/*
+// @match https://music.youtube.com/*
// @grant none
// @license MIT
// @compatible firefox
@@ -43,115 +40,263 @@
// @noframes
// ==/UserScript==
-interface YtdPlayerElement extends HTMLElement {
- getPlayer: () => YouTubePlayer
-}
-
/**
- * YouTube video player.
+ * Skip ads. Remove ad elements.
*/
-interface YouTubePlayer {
- getVideoData: () => YouTubeVideoData
- getCurrentTime: () => number
- loadVideoById: (videoId: string, startTime?: number) => void
-}
-
-interface YouTubeVideoData {
- title: string
- video_id: string
-}
-
function skipAd(): void {
- const isYouTubeShorts: boolean = checkIsYouTubeShorts()
- if (isYouTubeShorts) return
+ removeAdElements()
- const ad: HTMLElement | null = getInterruptiveAd()
- if (ad === null) return
+ video = null
+ fineScrubber = document.querySelector('.ytp-fine-scrubbing')
- const player: YouTubePlayer | null = getYouTubePlayer()
- if (player === null) return
+ // Check if the current URL is a YouTube Shorts URL and exit the function if true.
+ if (window.location.pathname.startsWith('/shorts/')) return
- ad.classList.remove('ad-showing')
+ const moviePlayer = document.querySelector('#movie_player')
- const videoData: YouTubeVideoData = player.getVideoData()
- const videoId: string = videoData.video_id
- const startTime: number = Math.floor(player.getCurrentTime())
- player.loadVideoById(videoId, startTime)
+ if (moviePlayer) {
+ hasAd = moviePlayer.classList.contains('ad-showing')
+ video = moviePlayer.querySelector('video.html5-main-video')
+ }
- console.log('Ad skipped!', videoId, startTime, videoData.title)
-}
+ if (hasAd) {
+ const skipButton = document.querySelector(`
+ .ytp-skip-ad-button,
+ .ytp-ad-skip-button,
+ .ytp-ad-skip-button-modern,
+ .ytp-ad-survey-answer-button
+ `)
+ // Click the skip ad button if available.
+ if (skipButton) {
+ skipButton.click()
+ skipButton.remove()
+ }
+ // Otherwise, fast forward to the end of the ad video.
+ // Use `9999` instead of `video.duration` to avoid errors when `duration` is not a number.
+ else if (video && video.src) {
+ video.currentTime = 9999
+ }
+ }
-function getInterruptiveAd(): HTMLElement | null {
- // This element appears when a video ad appears.
- const adShowing = document.querySelector('.ad-showing')
- if (adShowing !== null) return adShowing
+ if (video) {
+ video.addEventListener('pause', handleVideoPause)
+ video.addEventListener('pointerup', allowPauseVideo)
+ video.addEventListener('timeupdate', handleVideoTimeUpdate)
+ }
// Timed pie countdown ad.
const pieCountdown = document.querySelector(
'.ytp-ad-timed-pie-countdown-container'
)
- if (pieCountdown !== null) return pieCountdown
+ if (pieCountdown) {
+ pieCountdown.remove()
+ replaceCurrentVideo()
+ }
- return null
+ // Handle when ad blocker warning appears inside video player.
+ const adBlockerWarningInner = document.querySelector(
+ '.yt-playability-error-supported-renderers'
+ )
+ if (adBlockerWarningInner) {
+ adBlockerWarningInner.remove()
+ document.addEventListener('yt-navigate-finish', handleYouTubeNavigateFinish)
+ replaceCurrentVideo()
+ }
+
+ // Video play/pause button.
+ const playButton = document.querySelector(
+ 'button.ytp-play-button, button.player-control-play-pause-icon'
+ )
+ if (playButton) {
+ playButton.addEventListener('click', allowPauseVideo)
+ }
+}
+
+function queryHasSelector(
+ selector: string,
+ hasSelector: string,
+ element: Document | Element = document
+): T | null {
+ const el = element.querySelector(selector)
+ if (el === null) return null
+ const hasEl = el.querySelector(hasSelector)
+ if (hasEl === null) return null
+ return el
+}
+
+function queryHasSelectorAll(
+ selector: string,
+ hasSelector: string,
+ element: Document | Element = document
+): T[] {
+ const els = element.querySelectorAll(selector)
+ const result: T[] = []
+ for (const el of els) {
+ const hasEl = el.querySelector(hasSelector)
+ if (hasEl === null) continue
+ result.push(el)
+ }
+ return result
}
-function checkIsYouTubeShorts(): boolean {
- return location.pathname.startsWith('/shorts/')
+function getCurrentVideoId(): string | null {
+ const params = new URLSearchParams(location.search)
+ const videoId: string | null = params.get('v')
+ return videoId
}
/**
- * Finds and returns the current YouTube video player.
- *
- * @returns The current YouTube video player, or `null` if not found.
+ * Check if the user is focused on the input.
*/
-function getYouTubePlayer(): YouTubePlayer | null {
- let player: YouTubePlayer | null
- if (isYouTubeMobile) {
- const playerEl: unknown = document.querySelector('#movie_player')
- player = playerEl as YouTubePlayer
+function checkEnteringInput(): boolean {
+ if (document.activeElement === null) {
+ return false
+ }
+ return document.activeElement.matches('input, textarea, select')
+}
+
+/**
+ * Temporarily allows the video to be paused, for a short period of time.
+ */
+function allowPauseVideo(): void {
+ pausedByUser = true
+ window.clearTimeout(allowPauseVideoTimeoutId)
+ allowPauseVideoTimeoutId = window.setTimeout(disallowPauseVideo, 500)
+}
+
+/**
+ * Pausing the video is not allowed. The purpose is to prevent video from being paused,
+ * against the behavior of pausing video when YouTube ad blocking warning dialog appears.
+ * Unless certain conditions, such as pausing by user, etc.
+ */
+function disallowPauseVideo(): void {
+ pausedByUser = false
+ window.clearTimeout(allowPauseVideoTimeoutId)
+}
+
+function handleWindowBlur(): void {
+ isTabBlurred = true
+}
+
+function handleWindowFocus(): void {
+ isTabBlurred = false
+}
+
+/**
+ * Handle when video is paused. If certain conditions are not met, it will continue
+ * playing. Returning early in this function means the video should be paused as it should
+ * be.
+ */
+function handleVideoPause(): void {
+ if (isYouTubeMusic) return
+
+ // If it was stopped by the user, it's ok, let the video pause as it should, and exit the function.
+ if (pausedByUser) {
+ disallowPauseVideo()
+ return
+ }
+
+ // The video will pause normally if the tab is not focused. This is to allow for pausing the video via the media controller (of the browser or operating system), etc.
+ // Note: While this also gives YouTube the opportunity to pause videos to annoy users, it's an acceptable trade-off.
+ if (document.hidden) return
+ if (isTabBlurred) return
+
+ if (fineScrubber && fineScrubber.style.display !== 'none') return
+ if (video === null) return
+ if (video.duration - video.currentTime < 0.1) return
+
+ // This is YouTube's disruptive behavior towards users, so the video should continue to play as normal.
+ video.play()
+}
+
+function handleVideoTimeUpdate(): void {
+ if (hasAd || video === null) return
+ currentVideoTime = video.currentTime
+}
+
+/**
+ * Handle both keyboard press or release events.
+ */
+function handleWindowKeyDownAndKeyUp(event: KeyboardEvent): void {
+ if (isYouTubeMusic) return
+ if (checkEnteringInput()) return
+ const code: string = event.code
+ if (event.type === 'keydown') {
+ if (code === 'KeyK' || code === 'MediaPlayPause') {
+ allowPauseVideo()
+ }
} else {
- const playerEl = document.querySelector('#ytd-player')
- if (playerEl === null) return null
- player = playerEl.getPlayer()
+ if (code === 'Space') {
+ allowPauseVideo()
+ }
+ }
+}
+
+function handleYouTubeNavigateFinish(): void {
+ currentVideoTime = 0
+ replaceCurrentVideo()
+}
+
+async function replaceCurrentVideo(): Promise {
+ const start: number = Math.floor(currentVideoTime)
+ for (let i = 0; i < 16; i++) {
+ await waitFor(500)
+ const videoId: string | null = getCurrentVideoId()
+ if (!videoId || !video || video.src) continue
+ if (isYouTubeMobile) {
+ const player = document.querySelector('#movie_player')
+ if (!player) continue
+ player.loadVideoByPlayerVars({ videoId, start })
+ } else {
+ const player = document.querySelector('#ytd-player')
+ if (!player) continue
+ player.loadVideoWithPlayerVars({ videoId, start })
+ }
}
- return player
}
+function waitFor(millis: number): Promise {
+ return new Promise((resolve) => {
+ window.setTimeout(resolve, millis)
+ })
+}
+
+/**
+ * Add CSS hides some ad elements on the page.
+ */
function addCss(): void {
- const adsSelectors: string[] = [
+ const hideCssSelector: string = [
// Ad banner in the upper right corner, above the video playlist.
'#player-ads',
// Masthead ad on home page.
'#masthead-ad',
- // Sponsored ad video items on home page.
- // 'ytd-ad-slot-renderer',
-
- // '.ytp-suggested-action',
- '.yt-mealbar-promo-renderer',
+ 'ytd-ad-slot-renderer',
- // Featured product ad banner at the bottom left of the video.
- '.ytp-featured-product',
+ // Ad blocker warning inside the player.
+ 'yt-playability-error-supported-renderers#error-screen',
- // Products shelf ad banner below the video description.
- 'ytd-merch-shelf-renderer',
+ '.ytp-suggested-action',
+ '.yt-mealbar-promo-renderer',
// YouTube Music Premium trial promotion dialog, bottom left corner.
'ytmusic-mealbar-promo-renderer',
// YouTube Music Premium trial promotion banner on home page.
'ytmusic-statement-banner-renderer'
- ]
- const adsSelector: string = adsSelectors.join(',')
- const css: string = `${adsSelector} { display: none !important; }`
- const style = document.createElement('style')
+ ].join(',')
+ const css: string = `
+ #ytd-player { visibility: visible !important; }
+ ${hideCssSelector} { display: none !important; }
+ `
+ const style: HTMLStyleElement = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
}
/**
- * Remove ad elements using JavaScript because these selectors require the use of the CSS
+ * Remove ad elements using javascript because these selectors require the use of the CSS
* `:has` selector which is not supported in older browser versions.
*/
function removeAdElements(): void {
@@ -159,16 +304,19 @@ function removeAdElements(): void {
// Ad banner in the upper right corner, above the video playlist.
['#panels', 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]'],
+ // Temporarily comment out this selector to fix issue [#265124](https://greasyfork.org/en/scripts/498197-auto-skip-youtube-ads/discussions/265124).
+ // ['#panels', 'ytd-ads-engagement-panel-content-renderer'],
+
// Sponsored ad video items on home page.
// ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
// ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Short.
- ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
+ ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer'],
// Ad blocker warning dialog.
- // ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
+ ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model']
// Survey dialog on home page, located at bottom right.
// ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
@@ -177,19 +325,63 @@ function removeAdElements(): void {
// ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
- const adEl = document.querySelector(adSelector[0])
- if (adEl === null) continue
- const neededEl = adEl.querySelector(adSelector[1])
- if (neededEl === null) continue
- adEl.remove()
+ const adEls = queryHasSelectorAll(adSelector[0], adSelector[1])
+ for (const adEl of adEls) {
+ adEl.remove()
+ }
}
}
+/**
+ * Is it YouTube mobile version.
+ */
const isYouTubeMobile: boolean = location.hostname === 'm.youtube.com'
-window.setInterval(skipAd, 500)
-window.setInterval(removeAdElements, 1000)
+/**
+ * Is the current page YouTube Music.
+ */
+const isYouTubeMusic: boolean = location.hostname === 'music.youtube.com'
+
+/**
+ * Current video element.
+ */
+let video: HTMLVideoElement | null = null
+
+let fineScrubber: HTMLDivElement | null = null
+let hasAd: boolean = false
+let currentVideoTime: number = 0
+
+/**
+ * Is the video paused by the user, not paused by YouTube's ad blocker warning dialog.
+ */
+let pausedByUser: boolean = false
+
+/**
+ * Is the current tab blurred.
+ */
+let isTabBlurred: boolean = false
+
+let allowPauseVideoTimeoutId: number = 0
+
+// Observe DOM changes to detect ads.
+if (window.MutationObserver) {
+ const observer: MutationObserver = new MutationObserver(skipAd)
+ observer.observe(document.body, {
+ attributes: true,
+ attributeFilter: ['class', 'src'],
+ childList: true,
+ subtree: true
+ })
+}
+// If DOM observation is not supported. Detect ads every 500ms (2 times per second).
+else {
+ window.setInterval(skipAd, 500)
+}
+
+window.addEventListener('blur', handleWindowBlur)
+window.addEventListener('focus', handleWindowFocus)
+window.addEventListener('keydown', handleWindowKeyDownAndKeyUp)
+window.addEventListener('keyup', handleWindowKeyDownAndKeyUp)
addCss()
-removeAdElements()
skipAd()
From 6100c884a80e628d332170fbf4c1b8d8bfeb7991 Mon Sep 17 00:00:00 2001
From: tientq64
Date: Sun, 16 Feb 2025 01:25:25 +0700
Subject: [PATCH 06/19] Bug fix for YouTube Mobile
---
.resources/global.d.ts | 16 +++++
scripts/Auto-Skip-YouTube-Ads/script.user.js | 45 +++++++-------
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 63 +++++++-------------
3 files changed, 56 insertions(+), 68 deletions(-)
diff --git a/.resources/global.d.ts b/.resources/global.d.ts
index 8b51306..1b72fe7 100644
--- a/.resources/global.d.ts
+++ b/.resources/global.d.ts
@@ -51,6 +51,22 @@ declare const unsafeWindow: UnsafeWindow
interface YtdPlayerElement extends HTMLElement {
loadVideoWithPlayerVars(options: { videoId: string; start?: number }): void
+ getPlayer: () => YouTubePlayer
+}
+
+interface YouTubeMoviePlayerElement extends HTMLElement, YouTubePlayer {
+ loadVideoByPlayerVars(options: { videoId: string; start?: number }): void
+}
+
+interface YouTubePlayer {
+ getVideoData: () => YouTubeVideoData
+ getCurrentTime: () => number
+ loadVideoById: (videoId: string, startTime?: number) => void
+}
+
+interface YouTubeVideoData {
+ title: string
+ video_id: string
}
declare type TrustedTypePolicyFactory = import('trusted-types/lib').TrustedTypePolicyFactory
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index b47c3de..08a9b3b 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.3
+// @version 6.0.4
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -51,17 +51,30 @@ function skipAd() {
const ad = getInterruptiveAd()
if (ad === null) return
- const player = getYouTubePlayer()
- if (player === null) return
+ let playerEl
+ let player
+ if (isYouTubeMobile) {
+ playerEl = document.querySelector('#movie_player')
+ player = playerEl
+ } else {
+ playerEl = document.querySelector('#ytd-player')
+ player = playerEl && playerEl.getPlayer()
+ }
+ if (playerEl === null || player === null) return
- ad.classList.remove('ad-showing')
+ // ad.classList.remove('ad-showing')
const videoData = player.getVideoData()
const videoId = videoData.video_id
- const startTime = Math.floor(player.getCurrentTime())
- player.loadVideoById(videoId, startTime)
+ const start = Math.floor(player.getCurrentTime())
- console.log('Ad skipped!', videoId, startTime, videoData.title)
+ if ('loadVideoWithPlayerVars' in playerEl) {
+ playerEl.loadVideoWithPlayerVars({ videoId, start })
+ } else {
+ playerEl.loadVideoByPlayerVars({ videoId, start })
+ }
+
+ console.log('Ad skipped!', videoId, start, videoData.title)
}
function getInterruptiveAd() {
@@ -80,24 +93,6 @@ function checkIsYouTubeShorts() {
return location.pathname.startsWith('/shorts/')
}
-/**
- * Finds and returns the current YouTube video player.
- *
- * @returns The current YouTube video player, or `null` if not found.
- */
-function getYouTubePlayer() {
- let player
- if (isYouTubeMobile) {
- const playerEl = document.querySelector('#movie_player')
- player = playerEl
- } else {
- const playerEl = document.querySelector('#ytd-player')
- if (playerEl === null) return null
- player = playerEl.getPlayer()
- }
- return player
-}
-
function addCss() {
const adsSelectors = [
// Ad banner in the upper right corner, above the video playlist.
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index b934c94..a947404 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -14,7 +14,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 6.0.3
+// @version 6.0.4
// @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
@@ -43,24 +43,6 @@
// @noframes
// ==/UserScript==
-interface YtdPlayerElement extends HTMLElement {
- getPlayer: () => YouTubePlayer
-}
-
-/**
- * YouTube video player.
- */
-interface YouTubePlayer {
- getVideoData: () => YouTubeVideoData
- getCurrentTime: () => number
- loadVideoById: (videoId: string, startTime?: number) => void
-}
-
-interface YouTubeVideoData {
- title: string
- video_id: string
-}
-
function skipAd(): void {
const isYouTubeShorts: boolean = checkIsYouTubeShorts()
if (isYouTubeShorts) return
@@ -68,17 +50,30 @@ function skipAd(): void {
const ad: HTMLElement | null = getInterruptiveAd()
if (ad === null) return
- const player: YouTubePlayer | null = getYouTubePlayer()
- if (player === null) return
+ let playerEl: YtdPlayerElement | YouTubeMoviePlayerElement | null
+ let player: YouTubePlayer | YouTubeMoviePlayerElement | null
+ if (isYouTubeMobile) {
+ playerEl = document.querySelector('#movie_player')
+ player = playerEl
+ } else {
+ playerEl = document.querySelector('#ytd-player')
+ player = playerEl && playerEl.getPlayer()
+ }
+ if (playerEl === null || player === null) return
- ad.classList.remove('ad-showing')
+ // ad.classList.remove('ad-showing')
const videoData: YouTubeVideoData = player.getVideoData()
const videoId: string = videoData.video_id
- const startTime: number = Math.floor(player.getCurrentTime())
- player.loadVideoById(videoId, startTime)
+ const start: number = Math.floor(player.getCurrentTime())
- console.log('Ad skipped!', videoId, startTime, videoData.title)
+ if ('loadVideoWithPlayerVars' in playerEl) {
+ playerEl.loadVideoWithPlayerVars({ videoId, start })
+ } else {
+ playerEl.loadVideoByPlayerVars({ videoId, start })
+ }
+
+ console.log('Ad skipped!', videoId, start, videoData.title)
}
function getInterruptiveAd(): HTMLElement | null {
@@ -99,24 +94,6 @@ function checkIsYouTubeShorts(): boolean {
return location.pathname.startsWith('/shorts/')
}
-/**
- * Finds and returns the current YouTube video player.
- *
- * @returns The current YouTube video player, or `null` if not found.
- */
-function getYouTubePlayer(): YouTubePlayer | null {
- let player: YouTubePlayer | null
- if (isYouTubeMobile) {
- const playerEl: unknown = document.querySelector('#movie_player')
- player = playerEl as YouTubePlayer
- } else {
- const playerEl = document.querySelector('#ytd-player')
- if (playerEl === null) return null
- player = playerEl.getPlayer()
- }
- return player
-}
-
function addCss(): void {
const adsSelectors: string[] = [
// Ad banner in the upper right corner, above the video playlist.
From 5c572b80af60065b85a094d51987e5bd5f18c671 Mon Sep 17 00:00:00 2001
From: tientq64
Date: Mon, 17 Feb 2025 10:44:02 +0700
Subject: [PATCH 07/19] Remove unused `@types/trusted-types` lib
---
.resources/global.d.ts | 3 ---
package.json | 1 -
pnpm-lock.yaml | 8 --------
3 files changed, 12 deletions(-)
diff --git a/.resources/global.d.ts b/.resources/global.d.ts
index f3fbb53..50fff57 100644
--- a/.resources/global.d.ts
+++ b/.resources/global.d.ts
@@ -56,6 +56,3 @@ interface YtdPlayerElement extends HTMLElement {
interface YouTubeMoviePlayerElement extends HTMLElement {
loadVideoByPlayerVars(options: { videoId: string; start?: number }): void
}
-
-declare type TrustedTypePolicyFactory = import('trusted-types/lib').TrustedTypePolicyFactory
-declare const trustedTypes: TrustedTypePolicyFactory
diff --git a/package.json b/package.json
index 375ed01..d0ea677 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,6 @@
"@types/node": "^20.14.13",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
- "@types/trusted-types": "2.0.7",
"concurrently": "^8.2.2",
"eslint": "8.57.0",
"eslint-plugin-react": "^7.35.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index df8e21c..87cf79a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,9 +45,6 @@ importers:
'@types/react-dom':
specifier: 18.3.0
version: 18.3.0
- '@types/trusted-types':
- specifier: 2.0.7
- version: 2.0.7
concurrently:
specifier: ^8.2.2
version: 8.2.2
@@ -357,9 +354,6 @@ packages:
'@types/react@18.3.3':
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
- '@types/trusted-types@2.0.7':
- resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
-
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@@ -1906,8 +1900,6 @@ snapshots:
'@types/prop-types': 15.7.13
csstype: 3.1.3
- '@types/trusted-types@2.0.7': {}
-
'@types/unist@3.0.3': {}
'@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)':
From f60104f600d96883370b508b272b55d8a408e3c8 Mon Sep 17 00:00:00 2001
From: tientq64
Date: Thu, 20 Feb 2025 08:59:55 +0700
Subject: [PATCH 08/19] Remove some CSS
---
scripts/Auto-Skip-YouTube-Ads/script.user.js | 6 +++---
scripts/Auto-Skip-YouTube-Ads/script.user.ts | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.js b/scripts/Auto-Skip-YouTube-Ads/script.user.js
index feebd61..d7a2006 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.js
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.js
@@ -12,7 +12,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 7.0.0
+// @version 7.0.1
// @description Automatically skip YouTube ads almost instantly. Remove the ad blocker warning pop-up.
// @description:ar تخطي إعلانات YouTube تلقائيًا في الحال. إزالة النافذة المنبثقة لتحذير مانع الإعلانات.
// @description:es Omite automáticamente los anuncios de YouTube casi al instante. Elimina la ventana emergente de advertencia del bloqueador de anuncios.
@@ -263,12 +263,12 @@ function addCss() {
// Masthead ad on home page.
'#masthead-ad',
- 'ytd-ad-slot-renderer',
+ // 'ytd-ad-slot-renderer',
// Ad blocker warning inside the player.
'yt-playability-error-supported-renderers#error-screen',
- '.ytp-suggested-action',
+ // '.ytp-suggested-action',
'.yt-mealbar-promo-renderer',
// YouTube Music Premium trial promotion dialog, bottom left corner.
diff --git a/scripts/Auto-Skip-YouTube-Ads/script.user.ts b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
index 22c5f94..f38a06c 100644
--- a/scripts/Auto-Skip-YouTube-Ads/script.user.ts
+++ b/scripts/Auto-Skip-YouTube-Ads/script.user.ts
@@ -12,7 +12,7 @@
// @name:zh-CN 自动跳过 YouTube 广告
// @name:zh-TW 自動跳過 YouTube 廣告
// @namespace https://github.com/tientq64/userscripts
-// @version 7.0.0
+// @version 7.0.1
// @description Automatically skip YouTube ads almost instantly. Remove the ad blocker warning pop-up.
// @description:ar تخطي إعلانات YouTube تلقائيًا في الحال. إزالة النافذة المنبثقة لتحذير مانع الإعلانات.
// @description:es Omite automáticamente los anuncios de YouTube casi al instante. Elimina la ventana emergente de advertencia del bloqueador de anuncios.
@@ -272,12 +272,12 @@ function addCss(): void {
// Masthead ad on home page.
'#masthead-ad',
- 'ytd-ad-slot-renderer',
+ // 'ytd-ad-slot-renderer',
// Ad blocker warning inside the player.
'yt-playability-error-supported-renderers#error-screen',
- '.ytp-suggested-action',
+ // '.ytp-suggested-action',
'.yt-mealbar-promo-renderer',
// YouTube Music Premium trial promotion dialog, bottom left corner.
From c29dd507459b68c7a8f8130441e588895a81cbca Mon Sep 17 00:00:00 2001
From: tientq64
Date: Sat, 22 Feb 2025 12:28:47 +0700
Subject: [PATCH 09/19] Improve
---
.editorconfig | 11 +++
.resources/global.d.ts | 3 +
.vscode/settings.json | 3 +-
README.md | 96 ++++++++++++++++++++-
package.json | 2 +-
scripts/Tetr-io-Improvements/script.user.js | 10 +--
scripts/Tetr-io-Improvements/script.user.ts | 10 +--
tailwind.config.js => tailwind.config.ts | 6 +-
watch.ts | 37 ++++----
9 files changed, 143 insertions(+), 35 deletions(-)
create mode 100644 .editorconfig
rename tailwind.config.js => tailwind.config.ts (50%)
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..b311d28
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+root=true
+
+[*]
+end_of_line=lf
+charset=utf-8
+
+[*.{ts,tsx,js,json}]
+indent_style=tab
+indent_size=4
+trim_trailing_whitespace=true
+insert_final_newline=true
diff --git a/.resources/global.d.ts b/.resources/global.d.ts
index ab9c2c9..311cf31 100644
--- a/.resources/global.d.ts
+++ b/.resources/global.d.ts
@@ -38,6 +38,7 @@ type GMOpenInTabOptions = {
}
declare function GM_openInTab(url: string, options?: GMOpenInTabOptions): void
+declare type ReactElement = import('react').ReactElement
declare type ChangeEvent = import('react').ChangeEvent
declare type Immer = import('immer').Immer
@@ -61,12 +62,14 @@ interface YouTubeMoviePlayerElement extends HTMLElement, YouTubePlayer {
interface YouTubePlayer {
getVideoData: () => YouTubeVideoData
getCurrentTime: () => number
+ getDuration: () => number
loadVideoById: (videoId: string, startTime?: number) => void
}
interface YouTubeVideoData {
title: string
video_id: string
+ isLive: boolean
}
interface YouTubeMoviePlayerElement extends HTMLElement {
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a67c02d..8c48c71 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -19,6 +19,7 @@
},
"files.readonlyInclude": {
"scripts/*/{dev,script}.user.js": true,
- ".resources/tailwind.min.css": true
+ ".resources/tailwind.min.css": true,
+ "pnpm-lock.yaml": true
}
}
diff --git a/README.md b/README.md
index 1ff9d57..bba59aa 100644
--- a/README.md
+++ b/README.md
@@ -6,13 +6,82 @@
-The userscript collection I wrote makes life easier and better. I use the browser extension [TamperMonkey](https://www.tampermonkey.net) to run and manage userscripts. You need to install it first to use userscript.
+The userscript collection I wrote makes life easier and better. I use the browser extension [TamperMonkey][1] to run and manage userscripts. You need to install it first to use userscript.
+
+