Skip to content

Commit f68e189

Browse files
committed
feat(youtube): v1.0.5 - complete rewrite with 5-layer interception + DOM nuking
1 parent f75ac99 commit f68e189

7 files changed

Lines changed: 268 additions & 197 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<h1>PureShield</h1>
44
<p><strong>A comprehensive, privacy-first ad blocker, tracker blocker, and halal internet filter by SOCMID.</strong></p>
55

6-
[![Version](https://img.shields.io/badge/version-1.0.4-blue.svg)](https://github.com/SocMid/pureshield)
6+
[![Version](https://img.shields.io/badge/version-1.0.5-blue.svg)](https://github.com/SocMid/pureshield)
77
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/SocMid/pureshield/blob/main/LICENSE)
88
[![Platform](https://img.shields.io/badge/platform-Chrome%20|%20Edge%20|%20Brave-lightgrey.svg)](#)
99

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"manifest_version": 3,
33
"name": "PureShield",
44
"short_name": "PureShield",
5-
"version": "1.0.4",
5+
"version": "1.0.5",
66
"description": "Ad blocker, tracker blocker & halal filter. By SOCMID.",
77
"author": "SOCMID",
88
"permissions": [

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pureshield",
3-
"version": "1.0.4",
3+
"version": "1.0.5",
44
"description": "<div align=\"center\"> <img src=\"icons/icon128.png\" alt=\"PureShield Logo\" width=\"128\"> <h1>PureShield</h1> <p><strong>A comprehensive, privacy-first ad blocker, tracker blocker, and halal internet filter by SOCMID.</strong></p>",
55
"main": "background.js",
66
"scripts": {

popup.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
<div class="about-wrap">
139139
<img src="icons/icon128.png" class="about-logo" alt="PureShield" />
140140
<div class="about-name">PureShield</div>
141-
<div class="about-version">Version 1.0.4</div>
141+
<div class="about-version">Version 1.0.5</div>
142142
<div class="about-by">by SOCMID</div>
143143

144144
<div class="about-cards">

youtube_content.js

Lines changed: 132 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,172 @@
1-
// youtube_content.js – PureShield ULTRA MODE YouTube Ad Blocker (v1.0.4)
2-
// Strategy: "Physical Removal" to fix grid gaps + Skip fallback
1+
// youtube_content.js – PureShield v1.0.5 (Isolated World – DOM Cleanup)
2+
// Works alongside yt_scriptlet.js (Main World).
3+
// Handles: element removal, skip-button clicking, shielding overlay, anti-adblock dismissal.
34

45
(function () {
56
'use strict';
67

78
let adsEnabled = true;
8-
let wasAdPlaying = false;
99

10-
// ── Ultra Removal Selectors (Elements to COMPLETELY .remove()) ────────────
11-
const REMOVAL_SELECTORS = [
10+
// ── Elements to physically remove from the DOM ────────────────────
11+
const NUKE_SELECTORS = [
12+
// Homepage / feed ads
1213
'ytd-ad-slot-renderer',
1314
'ytd-rich-item-renderer:has(ytd-ad-slot-renderer)',
1415
'ytd-rich-item-renderer:has(ytd-in-feed-ad-layout-renderer)',
16+
'ytd-in-feed-ad-layout-renderer',
17+
'ytd-banner-promo-renderer',
18+
'ytd-statement-banner-renderer',
1519
'ytd-carousel-ad-renderer',
1620
'ytd-merch-shelf-renderer',
17-
'ytd-search-pyv-renderer',
18-
'ytd-promoted-video-renderer',
19-
'ytd-display-ad-renderer',
20-
'ytd-statement-banner-renderer',
21-
'ytd-in-feed-ad-layout-renderer',
22-
'ytd-compact-promoted-item-renderer',
2321
'ytd-brand-video-singleton-renderer',
2422
'ytd-brand-video-shelf-renderer',
2523
'#masthead-ad',
2624
'#player-ads',
25+
// Search ads
26+
'ytd-search-pyv-renderer',
27+
'ytd-promoted-video-renderer',
28+
'ytd-promoted-sparkles-web-renderer',
29+
// Sidebar / companion ads
2730
'ytd-action-companion-ad-renderer',
2831
'ytd-companion-slot-renderer',
29-
'ytd-promoted-sparkles-web-renderer',
30-
'ytd-mealbar-promo-renderer',
32+
'ytd-display-ad-renderer',
33+
'ytd-compact-promoted-item-renderer',
3134
'ytd-video-masthead-ad-v3-renderer',
32-
'ytd-enforcement-message-view-model',
33-
'tp-yt-paper-dialog.ytd-popup-container:has(#dismiss-button)',
34-
'tp-yt-iron-overlay-backdrop',
35+
'ytd-mealbar-promo-renderer',
36+
'#panels > ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]',
37+
// Player overlay ads
38+
'.ytp-ad-overlay-container',
3539
'.ytp-ad-module',
36-
'.ytp-ad-player-overlay-layout'
40+
'.ytp-ad-player-overlay-layout',
41+
'.ytp-ad-image-overlay',
42+
'.ytp-ad-text-overlay',
43+
'.ytp-ad-action-interstitial',
44+
// Anti-adblock popups
45+
'ytd-enforcement-message-view-model',
46+
'tp-yt-paper-dialog:has(yt-formatted-string#text.yt-about-this-ad-renderer)',
3747
];
3848

39-
let shieldEl = null;
40-
41-
function createShield() {
42-
if (shieldEl) return;
43-
shieldEl = document.createElement('div');
44-
shieldEl.id = 'pureshield-ultra-overlay';
45-
shieldEl.innerHTML = `
46-
<div class="pureshield-container">
47-
<div class="pureshield-logo-wrap">
48-
<div class="pureshield-logo">PureShield</div>
49-
<div class="pureshield-bolt">⚡</div>
50-
</div>
51-
<div class="pureshield-status">ULTRA MODE: Scriptlet Active</div>
52-
</div>
53-
`;
54-
const shieldStyle = document.createElement('style');
55-
shieldStyle.textContent = `
56-
#pureshield-ultra-overlay {
57-
position: absolute;
58-
top: 0; left: 0; width: 100%; height: 100%;
59-
background: radial-gradient(circle, #0a0a0a 0%, #000 100%);
60-
z-index: 2147483647; display: none;
61-
flex-direction: column; justify-content: center; align-items: center;
62-
color: #fff; font-family: 'Inter', sans-serif; pointer-events: none;
49+
// ── CSS to inject ────────────────────────────────────────────────
50+
function injectCSS() {
51+
const s = document.createElement('style');
52+
s.id = 'pureshield-v5-css';
53+
s.textContent = `
54+
/* Hide video element during ad playback */
55+
.ad-showing video,
56+
[class*="ad-interrupting"] video {
57+
opacity: 0 !important;
58+
pointer-events: none !important;
59+
}
60+
/* Hide player chrome during ad */
61+
.ad-showing .ytp-chrome-bottom,
62+
.ad-showing .ytp-chrome-top {
63+
opacity: 0 !important;
6364
}
64-
.ad-showing #pureshield-ultra-overlay, [class*="ad-interrupting"] #pureshield-ultra-overlay {
65-
display: flex !important;
65+
/* Visual shield overlay */
66+
#pureshield-shield {
67+
position: absolute; inset: 0;
68+
background: #000; z-index: 2147483647;
69+
display: none; place-items: center;
70+
color: #fff; font-family: 'Inter', sans-serif;
71+
pointer-events: none;
72+
}
73+
.ad-showing #pureshield-shield,
74+
[class*="ad-interrupting"] #pureshield-shield {
75+
display: grid !important;
76+
}
77+
#pureshield-shield .ps-logo {
78+
font-size: 26px; font-weight: 900;
79+
color: #2ecc71; letter-spacing: 3px;
80+
text-transform: uppercase;
81+
}
82+
#pureshield-shield .ps-sub {
83+
font-size: 12px; opacity: .6; margin-top: 8px;
84+
text-transform: uppercase; letter-spacing: 1px;
6685
}
67-
.pureshield-logo { font-size: 28px; font-weight: 900; color: #2ecc71; text-transform: uppercase; letter-spacing: 4px; }
68-
.pureshield-bolt { font-size: 24px; color: #f1c40f; }
69-
.pureshield-status { font-size: 13px; text-transform: uppercase; opacity: 0.7; margin-top: 10px; }
70-
.ad-showing video, [class*="ad-interrupting"] video { opacity: 0 !important; visibility: hidden !important; }
7186
`;
72-
document.head.appendChild(shieldStyle);
73-
74-
const mount = () => {
75-
const player = document.querySelector('#movie_player') || document.querySelector('.html5-video-player');
76-
if (player && !player.contains(shieldEl)) player.appendChild(shieldEl);
77-
};
78-
mount();
79-
setInterval(mount, 2000);
87+
(document.head || document.documentElement).appendChild(s);
88+
}
89+
90+
// ── Shield overlay ───────────────────────────────────────────────
91+
function mountShield() {
92+
const player = document.querySelector('#movie_player, .html5-video-player');
93+
if (!player || player.querySelector('#pureshield-shield')) return;
94+
const d = document.createElement('div');
95+
d.id = 'pureshield-shield';
96+
d.innerHTML = '<div><div class="ps-logo">PureShield ⚡</div><div class="ps-sub">Ad neutralized</div></div>';
97+
player.appendChild(d);
8098
}
8199

82-
function removeAds() {
100+
// ── Core cleanup loop ────────────────────────────────────────────
101+
function cleanup() {
83102
if (!adsEnabled) return;
84-
85-
// 1. Physical Removal to fix grid layout
86-
REMOVAL_SELECTORS.forEach(selector => {
87-
document.querySelectorAll(selector).forEach(el => {
88-
// If it's a rich-item-renderer, we should be careful to re-flow
89-
el.remove();
90-
// Trigger resize event to force YouTube to recalculate grid
91-
window.dispatchEvent(new Event('resize'));
92-
});
93-
});
94103

95-
// 2. Video Skip Fallback
96-
const video = document.querySelector('video');
97-
const adActive = !!(document.querySelector('.ad-showing') || document.querySelector('[class*="ad-interrupting"]'));
104+
// 1. Remove ad elements
105+
for (const sel of NUKE_SELECTORS) {
106+
const els = document.querySelectorAll(sel);
107+
if (els.length) {
108+
els.forEach(el => el.remove());
109+
}
110+
}
111+
112+
// 2. Dismiss anti-adblock overlays
113+
const overlays = document.querySelectorAll('tp-yt-iron-overlay-backdrop');
114+
overlays.forEach(o => o.remove());
115+
// Click dismiss / continue buttons
116+
const dismiss = document.querySelector(
117+
'#dismiss-button, .yt-about-this-ad-renderer button, tp-yt-paper-dialog #dismiss-button'
118+
);
119+
if (dismiss) dismiss.click();
98120

121+
// 3. Mount shield if needed
122+
mountShield();
123+
124+
// 4. Skip / jump video ads
125+
const adActive = document.querySelector('.ad-showing, [class*="ad-interrupting"]');
126+
const video = document.querySelector('video');
99127
if (adActive && video) {
100-
wasAdPlaying = true;
101-
102-
// Instant skip button click
103-
const skip = document.querySelector('.ytp-skip-ad-button, .ytp-ad-skip-button, .ytp-ad-skip-button-modern');
104-
if (skip) skip.click();
105-
106-
// Speed up + Jump
107-
if (video.duration && isFinite(video.duration)) {
108-
video.currentTime = video.duration - 0.1;
109-
}
110-
video.playbackRate = 16;
111-
video.muted = true;
112-
} else if (wasAdPlaying && !adActive) {
113-
wasAdPlaying = false;
114-
if (video) {
115-
video.playbackRate = 1;
116-
video.muted = false;
117-
}
128+
// Click skip button instantly
129+
const skip = document.querySelector(
130+
'.ytp-skip-ad-button, .ytp-ad-skip-button, .ytp-ad-skip-button-modern, .ytp-ad-skip-button-slot button'
131+
);
132+
if (skip && skip.offsetParent !== null) {
133+
skip.click();
134+
return;
135+
}
136+
// Jump to end
137+
if (video.duration && isFinite(video.duration) && video.duration > 0.5) {
138+
video.currentTime = video.duration - 0.1;
139+
}
140+
video.playbackRate = 16;
141+
video.muted = true;
118142
}
119143
}
120144

145+
// ── Init ──────────────────────────────────────────────────────────
121146
function init() {
122-
chrome.storage.local.get(['filters'], (saved) => {
123-
adsEnabled = saved.filters ? saved.filters.ads !== false : true;
124-
if (adsEnabled) {
125-
createShield();
126-
// Polling for physical cleanup
127-
setInterval(removeAds, 100);
128-
// Instant removal for home grid
129-
const observer = new MutationObserver(removeAds);
130-
observer.observe(document.body, { childList: true, subtree: true });
131-
}
147+
chrome.storage.local.get(['filters'], (result) => {
148+
adsEnabled = result.filters ? result.filters.ads !== false : true;
149+
if (!adsEnabled) return;
150+
151+
injectCSS();
152+
153+
// Run cleanup immediately and on interval
154+
cleanup();
155+
setInterval(cleanup, 150);
156+
157+
// MutationObserver for instant reaction
158+
const obs = new MutationObserver(cleanup);
159+
obs.observe(document.documentElement, { childList: true, subtree: true });
132160
});
133161
}
134162

163+
// Listen for setting changes
164+
chrome.storage.onChanged.addListener((changes) => {
165+
if (changes.filters) {
166+
adsEnabled = changes.filters.newValue.ads !== false;
167+
}
168+
});
169+
135170
if (document.readyState === 'loading') {
136171
document.addEventListener('DOMContentLoaded', init);
137172
} else {

0 commit comments

Comments
 (0)