Skip to content

Commit 9679363

Browse files
committed
modified: youtube-byp/ytbyp.js
1 parent f44a135 commit 9679363

1 file changed

Lines changed: 147 additions & 25 deletions

File tree

youtube-byp/ytbyp.js

Lines changed: 147 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// ==UserScript==
2-
// @name YT Music Autoclicker API (Proactive & Stealth Edition)
2+
// @name YT Music Autoclicker API (Hybrid Core Edition)
33
// @namespace https://github.com/fgirolami29
4-
// @version 3.1.0
5-
// @description Previene il popup di YT Music tramite reset API core e disabilita la telemetria/logging di YouTube.
4+
// @version 3.2.0
5+
// @description Bypass proattivo via API core, sinkhole telemetrico e fallback reattivo a due stadi (Spacebar emulata + Notifica OS Focus). Zero errori TS.
66
// @author Tu & Gemini
77
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAgCAYAAACLmoEDAAABo0lEQVR4AdSXAZKDIBAEiR878zL1Zbmf5aY3txaWpqKyWCS1I4jotiMi6VLh75lSv1eFqdIKNks8qv7I9FR9JQE89mrr/KzNc5HXpOsuYgGrE0cd9eSD6n0mVauG5yKvCR7kWWdYNSoSnfxYCyU8g8C4kdcw0A6OtgD3jgHoF6x62I7KVsNe4k6umsWtUmZcA2P2W2DnYZDdQLPVHmd/AvB+A67x8RLAfuy0o8N0S0mRplTxFwVriKJlCqwGDGzoCwawpIh3GVhzJXoj2lFSxEFXg/WbF60PjeLhUR0WaICR6kXAl8AK0oMpDvn+ofISWD7pki89T7/Q1WEFyZgF9DSk218NFkhJEbdGBvb0GPI7zkvRsZzDyfBlJ7B5rtP1DBLQ4ke+BRIFi4vVIB08CvaQk578aAls0UR9NGFJf2BLzr/y3KnTZzB0NqhJ7842PxRk6miwVORIyw6bmQYr0CTgu0prVNlKYOBdbHyyl/9uaZQUCWhEZ3QFPHlc5AYS0Wb5Z2dt738jWlb5iM7opraV1J2ncVhb11IbeVzkniGVx+IPAAD///H503IAAAAGSURBVAMApvWIs8xfbPkAAAAASUVORK5CYII=
88
// @include *://music.youtube.com/**
@@ -13,20 +13,24 @@
1313
/* eslint-env browser, greasemonkey */
1414
/* global globalThis */
1515

16-
const VERSION = '3.1.0';
16+
const VERSION = '3.2.0';
17+
const ICON_BASE64 =
18+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAgCAYAAACLmoEDAAABo0lEQVR4AdSXAZKDIBAEiR878zL1Zbmf5aY3txaWpqKyWCS1I4jotiMi6VLh75lSv1eFqdIKNks8qv7I9FR9JQE89mrr/KzNc5HXpOsuYgGrE0cd9eSD6n0mVauG5yKvCR7kWWdYNSoSnfxYCyU8g8C4kdcw0A6OtgD3jgHoF6x62I7KVsNe4k6umsWtUmZcA2P2W2DnYZDdQLPVHmd/AvB+A67x8RLAfuy0o8N0S0mRplTxFwVriKJlCqwGDGzoCwawpIh3GVhzJXoj2lFSxEFXg/WbF60PjeLhUR0WaICR6kXAl8AK0oMpDvn+ofISWD7pki89T7/Q1WEFyZgF9DSk218NFkhJEbdGBvb0GPI7zkvRsZzDyfBlJ7B5rtP1DBLQ4ke+BRIFi4vVIB08CvaQk578aAls0UR9NGFJf2BLzr/y3KnTZzB0NqhJ7842PxRk6miwVORIyw6bmQYr0CTgu0prVNlKYOBdbHyyl/9uaZQUCWhEZ3QFPHlc5AYS0Wb5Z2dt738jWlb5iM7opraV1J2ncVhb11IbeVzkniGVx+IPAAD///H503IAAAAGSURBVAMApvWIs8xfbPkAAAAASUVORK5CYII=';
1719

1820
/**
1921
* @typedef {Object} YTBYP_Config
2022
* @property {number} pingIntervalMs - Intervallo di reset del timer AFK (default: 5 min).
2123
* @property {boolean} blockTelemetry - Flag per abilitare/disabilitare il sinkhole network.
2224
* @property {boolean} debugMode - Flag per abilitare/disabilitare l'output verboso.
25+
* @property {number} fallbackTimeoutMs - Timeout prima di innescare la notifica OS di emergenza (ms).
2326
*/
2427

2528
/** @type {YTBYP_Config} */
2629
const CONFIG = {
2730
pingIntervalMs: 5 * 60 * 1000,
2831
blockTelemetry: true,
29-
debugMode: true
32+
debugMode: true,
33+
fallbackTimeoutMs: 2000,
3034
};
3135

3236
(function (window, globalThis) {
@@ -36,6 +40,10 @@ const CONFIG = {
3640
const _global = globalThis;
3741
const targetWindow = typeof _global.unsafeWindow !== 'undefined' ? _global.unsafeWindow : window;
3842

43+
/**
44+
* Dispatcher standardizzato per output di log diagnostici.
45+
* @param {string} message
46+
*/
3947
const debug = (message) => {
4048
if (!CONFIG.debugMode) return;
4149
const prefix = '[YT Music Bypass] ';
@@ -46,12 +54,16 @@ const CONFIG = {
4654
}
4755
};
4856

57+
/**
58+
* API Pubblica esportata nel window per debug e controllo runtime.
59+
*/
4960
const API = {
5061
config: CONFIG,
5162
interval: undefined,
63+
modalObserver: undefined,
5264
start: () => {},
5365
stop: () => {},
54-
forcePing: () => {}
66+
forcePing: () => {},
5567
};
5668

5769
/**
@@ -63,25 +75,25 @@ const CONFIG = {
6375

6476
// 1. Intercettazione Fetch API
6577
const originalFetch = window.fetch;
66-
window.fetch = async function(...args) {
78+
window.fetch = async function (...args) {
6779
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
6880
const blockList = ['/youtubei/v1/log_event', '/api/stats/qoe', '/api/stats/playback', 'ptracking', 'play_tracking'];
6981

70-
if (blockList.some(endpoint => url.includes(endpoint))) {
82+
if (blockList.some((endpoint) => url.includes(endpoint))) {
7183
debug(`[Sinkhole] Fetch droppata: ${url.split('?')[0]}`);
7284
return new Response(JSON.stringify({}), { status: 200, statusText: 'OK' });
7385
}
7486
return originalFetch.apply(this, args);
7587
};
7688

77-
// 2. Intercettazione XHR
89+
// 2. Intercettazione XHR (Trasporto Legacy)
7890
const originalXhrOpen = XMLHttpRequest.prototype.open;
79-
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
91+
XMLHttpRequest.prototype.open = function (method, url, ...rest) {
8092
const blockList = ['/log_event', '/stats/', 'ptracking'];
81-
82-
if (typeof url === 'string' && blockList.some(endpoint => url.includes(endpoint))) {
93+
94+
if (typeof url === 'string' && blockList.some((endpoint) => url.includes(endpoint))) {
8395
debug(`[Sinkhole] XHR droppata: ${url.split('?')[0]}`);
84-
this.send = function() {
96+
this.send = function () {
8597
Object.defineProperty(this, 'readyState', { value: 4 });
8698
Object.defineProperty(this, 'status', { value: 200 });
8799
Object.defineProperty(this, 'responseText', { value: '{}' });
@@ -96,12 +108,20 @@ const CONFIG = {
96108
// 3. Stubbing Metodi Nativi Core Player
97109
const overrideCoreLogging = () => {
98110
const playerEl = document.querySelector('ytmusic-player');
99-
const corePlayer = playerEl ? /** @type {any} */(playerEl).getPlayer?.() : null;
111+
const corePlayer = playerEl ? /** @type {any} */ (playerEl).getPlayer?.() : null;
100112
if (!corePlayer) return;
101113

102-
const logMethods = ['logImaAdEvent', 'logApiCall', 'logClick', 'logVisibility', 'sendImpression', 'impressionLog', 'setTrackingParams'];
114+
const logMethods = [
115+
'logImaAdEvent',
116+
'logApiCall',
117+
'logClick',
118+
'logVisibility',
119+
'sendImpression',
120+
'impressionLog',
121+
'setTrackingParams',
122+
];
103123
let patched = 0;
104-
logMethods.forEach(method => {
124+
logMethods.forEach((method) => {
105125
if (typeof corePlayer[method] === 'function') {
106126
corePlayer[method] = () => {};
107127
patched++;
@@ -113,45 +133,147 @@ const CONFIG = {
113133
setTimeout(overrideCoreLogging, 5000);
114134
};
115135

136+
/**
137+
* Esegue il ping alle API interne per resettare i contatori di attività locale e server-side.
138+
*/
116139
const executeEngagementPing = () => {
117140
const playerEl = document.querySelector('ytmusic-player');
118-
const corePlayer = playerEl ? /** @type {any} */(playerEl).getPlayer?.() : null;
141+
const corePlayer = playerEl ? /** @type {any} */ (playerEl).getPlayer?.() : null;
119142

120143
if (corePlayer) {
121144
let successCount = 0;
122-
if (typeof corePlayer.updateLastActiveTime === 'function') { corePlayer.updateLastActiveTime(); successCount++; }
123-
if (typeof corePlayer.setUserEngagement === 'function') { corePlayer.setUserEngagement(); successCount++; }
145+
if (typeof corePlayer.updateLastActiveTime === 'function') {
146+
corePlayer.updateLastActiveTime();
147+
successCount++;
148+
}
149+
if (typeof corePlayer.setUserEngagement === 'function') {
150+
corePlayer.setUserEngagement();
151+
successCount++;
152+
}
124153
if (successCount > 0) debug('✅ Ping inviato. Timer inattività (AFK) azzerato.');
125154
}
126155
};
127156

157+
/**
158+
* Valuta l'effettiva visibilità di un nodo nel DOM.
159+
* @param {Element | null} el
160+
*/
161+
const isVisible = (el) => {
162+
if (!el) return false;
163+
const style = window.getComputedStyle(el);
164+
return (
165+
style.display !== 'none' &&
166+
style.visibility !== 'hidden' &&
167+
style.opacity !== '0' &&
168+
/** @type {HTMLElement} */ (el).offsetWidth > 0
169+
);
170+
};
171+
172+
/**
173+
* Esegue il dispatcher di fallback reattivo monitorando il DOM per instanziazioni anomale del modal.
174+
*/
175+
const initReactiveFallback = () => {
176+
debug('Avvio strato di fallback reattivo (Observer su Body)...');
177+
178+
API.modalObserver = new MutationObserver((mutations) => {
179+
for (const mutation of mutations) {
180+
for (const node of mutation.addedNodes) {
181+
if (node.nodeType === 1) {
182+
const el = /** @type {HTMLElement} */ (node);
183+
const modal = el.tagName === 'YTMUSIC-YOU-THERE-RENDERER' ? el : el.querySelector('ytmusic-you-there-renderer');
184+
185+
if (modal) {
186+
debug('🚨 Fallback Innescato: Rilevato modal AFK nonostante il ping proattivo.');
187+
188+
// Livello Fallback 1: Simulazione nativa Spacebar
189+
const spaceEvent = new KeyboardEvent('keydown', {
190+
key: ' ',
191+
code: 'Space',
192+
keyCode: 32,
193+
bubbles: true,
194+
cancelable: true,
195+
});
196+
document.body.dispatchEvent(spaceEvent);
197+
debug('Tasto Spazio emulato e dislocato sul body.');
198+
199+
// Livello Fallback 2: Notifica OS interattiva (Extrema Ratio)
200+
setTimeout(() => {
201+
if (isVisible(modal) && 'Notification' in window) {
202+
debug('⚠️ Spacebar fallita o ignorata. Lancio notifica OS di emergenza.');
203+
204+
const spawnNotification = () => {
205+
const n = new Notification('YT Music Bloccato ⏸️', {
206+
body: 'Il blocco AFK ha eluso i controlli. Clicca per forzare il focus e riprendere.',
207+
icon: ICON_BASE64,
208+
requireInteraction: true,
209+
});
210+
211+
n.onclick = () => {
212+
window.focus();
213+
n.close();
214+
215+
// Esecuzione forza bruta sul nodo bottone come clean-up finale
216+
const yesBtn =
217+
document.querySelector('yt-button-renderer[dialog-confirm] button') ||
218+
modal.querySelector('button');
219+
if (yesBtn) {
220+
/** @type {HTMLElement} */ (yesBtn).click();
221+
debug('Focus completato. Click fisico sul DOM eseguito.');
222+
}
223+
};
224+
};
225+
226+
if (Notification.permission === 'granted') {
227+
spawnNotification();
228+
} else if (Notification.permission !== 'denied') {
229+
Notification.requestPermission().then((p) => p === 'granted' && spawnNotification());
230+
}
231+
} else {
232+
debug('✅ Modal risolto dalla spacebar. Nessun intervento OS richiesto.');
233+
}
234+
}, CONFIG.fallbackTimeoutMs);
235+
}
236+
}
237+
}
238+
}
239+
});
240+
241+
API.modalObserver.observe(document.body, { childList: true, subtree: true });
242+
};
243+
128244
let isRunning = false;
129245

130246
API.start = () => {
131247
if (isRunning) return;
132248
isRunning = true;
133-
134-
debug(`Inizializzazione v${VERSION}.`);
249+
250+
debug(`Inizializzazione v${VERSION} [Hybrid Core Architecture].`);
251+
252+
// Setup Componenti
135253
initTelemetryBlocker();
254+
initReactiveFallback();
136255

256+
// Innesco Routine
137257
setTimeout(executeEngagementPing, 10000);
138258
API.interval = window.setInterval(executeEngagementPing, CONFIG.pingIntervalMs);
139259
};
140260

141261
API.stop = () => {
142262
isRunning = false;
143263
if (API.interval !== undefined) clearInterval(API.interval);
144-
debug('Demone arrestato. Protezione AFK disattivata.');
264+
if (API.modalObserver) API.modalObserver.disconnect();
265+
debug('Demone arrestato. Protezione disattivata.');
145266
};
146267

147268
API.forcePing = executeEngagementPing;
148269

270+
// Binding Global
149271
targetWindow.ytbyp = API;
150-
272+
273+
// Auto-avvio sicuro
151274
if (document.readyState === 'complete' || document.readyState === 'interactive') {
152275
API.start();
153276
} else {
154277
document.addEventListener('DOMContentLoaded', API.start);
155278
}
156-
157-
})(window, globalThis);
279+
})(window, globalThis);

0 commit comments

Comments
 (0)