11// ==UserScript==
22// @name YT Music Autoclicker API (Stealth Trap Edition)
33// @namespace https://github.com/fgirolami29
4- // @version 2.1.1
5- // @description Bypassa popup YT Music con Notifiche Interattive, IntersectionObserver e API di debug. Zero errori TS.
4+ // @version 2.2.0
5+ // @description Bypassa popup YT Music con Notifiche Interattive, IntersectionObserver e API di debug configurabili . 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/**
1313/* eslint-env browser, greasemonkey */
1414/* global globalThis */
1515
16- const VERSION = '2.1.1 ' ;
16+ const VERSION = '2.2.0 ' ;
1717const ICON_BASE64 =
1818 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAgCAYAAACLmoEDAAABo0lEQVR4AdSXAZKDIBAEiR878zL1Zbmf5aY3txaWpqKyWCS1I4jotiMi6VLh75lSv1eFqdIKNks8qv7I9FR9JQE89mrr/KzNc5HXpOsuYgGrE0cd9eSD6n0mVauG5yKvCR7kWWdYNSoSnfxYCyU8g8C4kdcw0A6OtgD3jgHoF6x62I7KVsNe4k6umsWtUmZcA2P2W2DnYZDdQLPVHmd/AvB+A67x8RLAfuy0o8N0S0mRplTxFwVriKJlCqwGDGzoCwawpIh3GVhzJXoj2lFSxEFXg/WbF60PjeLhUR0WaICR6kXAl8AK0oMpDvn+ofISWD7pki89T7/Q1WEFyZgF9DSk218NFkhJEbdGBvb0GPI7zkvRsZzDyfBlJ7B5rtP1DBLQ4ke+BRIFi4vVIB08CvaQk578aAls0UR9NGFJf2BLzr/y3KnTZzB0NqhJ7842PxRk6miwVORIyw6bmQYr0CTgu0prVNlKYOBdbHyyl/9uaZQUCWhEZ3QFPHlc5AYS0Wb5Z2dt738jWlb5iM7opraV1J2ncVhb11IbeVzkniGVx+IPAAD///H503IAAAAGSURBVAMApvWIs8xfbPkAAAAASUVORK5CYII=' ;
1919
20+ /**
21+ * @typedef {Object } YTBYP_Config
22+ * @property {number } checkIntervalMs - Frequenza del loop di ricerca bottone (ms).
23+ * @property {number } maxAttempts - Numero massimo di iterazioni del loop prima del timeout.
24+ * @property {number } restartDelayMs - Ritardo avvio loop dopo il click sulla notifica (ms).
25+ * @property {number } observerThreshold - Ratio di visibilità per triggerare l'observer (0.0 - 1.0).
26+ * @property {boolean } debugMode - Flag per abilitare/disabilitare l'output di debug.
27+ */
28+
29+ /** @type {YTBYP_Config } */
30+ const CONFIG = {
31+ checkIntervalMs : 200 ,
32+ maxAttempts : 50 ,
33+ restartDelayMs : 150 ,
34+ observerThreshold : 0.1 ,
35+ debugMode : true ,
36+ } ;
37+
2038( function ( window , globalThis ) {
2139 'use strict' ;
2240
2341 /** @typedef {{ message: string, attempts?: number, success?: boolean } } YTBypEventDetail */
2442
2543 /**
2644 * @typedef {Object } YTBYP_API
45+ * @property {YTBYP_Config } config
2746 * @property {() => void } start
2847 * @property {() => void } stop
2948 * @property {() => void } forceCheck
@@ -42,7 +61,9 @@ const ICON_BASE64 =
4261 /** @type {Window & { cccg?: {ccLog?: (m: string) => void}, ytbyp?: YTBYP_API } } */
4362 const targetWindow = typeof _global . unsafeWindow !== 'undefined' ? _global . unsafeWindow : window ;
4463
45- /** @param {Element | null } el */
64+ /** * Valuta l'effettiva visibilità di un nodo nel DOM.
65+ * @param {Element | null } el
66+ */
4667 const isVisible = ( el ) => {
4768 if ( ! el ) return false ;
4869 if ( el . hasAttribute ( 'hidden' ) ) return false ;
@@ -55,7 +76,8 @@ const ICON_BASE64 =
5576 ) ;
5677 } ;
5778
58- /** * @param {string } title
79+ /** * Genera la notifica di sistema interattiva.
80+ * @param {string } title
5981 * @param {string } body
6082 * @param {Function } [onClickCallback]
6183 */
@@ -65,13 +87,13 @@ const ICON_BASE64 =
6587 const options = {
6688 body,
6789 icon : ICON_BASE64 ,
68- requireInteraction : true , // Non scompare finché non la clicchi
90+ requireInteraction : true , // Persistenza attiva finché non interagita
6991 } ;
7092
7193 const spawn = ( ) => {
7294 const n = new Notification ( title , options ) ;
7395 n . onclick = ( ) => {
74- window . focus ( ) ; // Evoca la finestra di YT Music in primo piano
96+ window . focus ( ) ; // Richiama il focus sulla finestra di YT Music
7597 n . close ( ) ;
7698 if ( onClickCallback ) onClickCallback ( ) ;
7799 } ;
@@ -85,6 +107,7 @@ const ICON_BASE64 =
85107 } ;
86108
87109 /**
110+ * Dispatcher centralizzato per log console ed eventi custom DOM.
88111 * @param {string } eventName
89112 * @param {string } message
90113 * @param {{ attempts?: number, success?: boolean } } [extraPayload={}]
@@ -93,7 +116,12 @@ const ICON_BASE64 =
93116 const prefix = '[YT Music Autoclicker] ' ;
94117 if ( typeof targetWindow . cccg ?. ccLog === 'function' ) {
95118 targetWindow . cccg . ccLog ( prefix + message ) ;
96- } else console . log ( prefix + message ) ;
119+ } else {
120+ // Esegue il console.log standard solo se non è un messaggio di debug o se la config debugMode è attiva
121+ if ( eventName !== 'ytbyp:debug' || CONFIG . debugMode ) {
122+ console . log ( prefix + message ) ;
123+ }
124+ }
97125
98126 document . dispatchEvent ( new CustomEvent ( eventName , { detail : { message, ...extraPayload } } ) ) ;
99127
@@ -106,11 +134,16 @@ const ICON_BASE64 =
106134 }
107135 } ;
108136
109- /** @param {string } msg */
110- const debug = ( msg ) => dispatchLog ( 'ytbyp:debug' , msg ) ;
137+ /** * Wrapper per i messaggi di routine, filtrati dalla configurazione.
138+ * @param {string } msg
139+ */
140+ const debug = ( msg ) => {
141+ if ( CONFIG . debugMode ) dispatchLog ( 'ytbyp:debug' , msg ) ;
142+ } ;
111143
112144 /** @type {YTBYP_API } */
113145 const API = {
146+ config : CONFIG ,
114147 start : ( ) => { } ,
115148 stop : ( ) => { } ,
116149 forceCheck : ( ) => { } ,
@@ -175,17 +208,17 @@ const ICON_BASE64 =
175208 attempts ++ ;
176209 }
177210
178- if ( attempts >= 50 ) {
211+ if ( attempts >= CONFIG . maxAttempts ) {
179212 clearInterval ( API . interval ) ;
180- dispatchLog ( 'ytbyp:max-attempts' , ' Limite 50 tentativi raggiunto.' , {
213+ dispatchLog ( 'ytbyp:max-attempts' , ` Limite ${ CONFIG . maxAttempts } tentativi raggiunto.` , {
181214 attempts,
182215 success : false ,
183216 } ) ;
184217 }
185- } , 200 ) ;
218+ } , CONFIG . checkIntervalMs ) ;
186219 } ;
187220
188- /** * L'Observer Stealth
221+ /** * L'Observer Stealth per l'intercettazione del popup.
189222 * @param {Element } modalElement
190223 */
191224 const attachVisibilityObserver = ( modalElement ) => {
@@ -201,21 +234,21 @@ const ICON_BASE64 =
201234 if ( entry . isIntersecting ) {
202235 debug ( '⚠️ Il modal di pausa è apparso! Innesco la notifica-trappola...' ) ;
203236
204- // LA MAGIA: Invece di cliccare subito, ti chiamo tramite notifica
237+ // Sospende l'esecuzione e attende il click sulla notifica
205238 sendInteractiveNotification (
206239 'YT Music in Pausa ⏸️' ,
207240 'YouTube chiede se ci sei. Clicca qui per riprendere la musica!' ,
208241 ( ) => {
209242 debug ( "Notifica cliccata! Riprendo l'ascolto e chiudo il popup." ) ;
210- setTimeout ( startClickLoop , 150 ) ;
243+ setTimeout ( startClickLoop , CONFIG . restartDelayMs ) ;
211244 } ,
212245 ) ;
213246 }
214247 }
215248 } ,
216249 {
217- root : null , // Guarda l 'intera viewport del browser
218- threshold : 0.1 , // Basta che appaia il 10% del popup per attivarsi
250+ root : null , // Rilevamento sull 'intera viewport
251+ threshold : CONFIG . observerThreshold , // Ratio di attivazione configurabile
219252 } ,
220253 ) ;
221254
@@ -228,14 +261,14 @@ const ICON_BASE64 =
228261 if ( isRunning ) return ;
229262 isRunning = true ;
230263
231- // 1. Cerca il modal se è già stato iniettato da YouTube
264+ // 1. Hook iniziale su modal preesistenti
232265 const existingModal = document . querySelector ( 'ytmusic-you-there-renderer' ) ;
233266 if ( existingModal ) {
234267 debug ( "Modal trovato nel DOM all'avvio. Pre-aggancio IntersectionObserver." ) ;
235268 attachVisibilityObserver ( existingModal ) ;
236269 }
237270
238- // 2. Observer di sicurezza per la primissima iniezione nel body
271+ // 2. Observer di sicurezza per la mutazione del body
239272 API . bodyObserver = new MutationObserver ( ( m ) => {
240273 for ( const mut of m ) {
241274 for ( const node of mut . addedNodes ) {
0 commit comments