// ==UserScript== // @name ๐ŸŽธ Songsterr Ultimate (Premium Unlocked) // @name:en ๐ŸŽธ Songsterr Ultimate (Premium Unlocked) // @name:fr ๐ŸŽธ Songsterr Ultime (Premium Dรฉbloquรฉ) // @name:es ๐ŸŽธ Songsterr Definitivo (Premium Desbloqueado) // @name:de ๐ŸŽธ Songsterr Ultimativ (Premium Freigeschaltet) // @name:it ๐ŸŽธ Songsterr Definitivo (Premium Sbloccato) // @name:pt ๐ŸŽธ Songsterr Supremo (Premium Desbloqueado) // @name:pt-BR ๐ŸŽธ Songsterr Supremo (Full Premium) // @name:nl ๐ŸŽธ Songsterr Ultiem (Premium Ontgrendeld) // @name:pl ๐ŸŽธ Songsterr Ostateczny (Premium Odblokowany) // @name:ru ๐ŸŽธ Songsterr ะะฑัะพะปัŽั‚ะฝั‹ะน (ะŸั€ะตะผะธัƒะผ ะ ะฐะทะฑะปะพะบะธั€ะพะฒะฐะฝ) // @name:ja ๐ŸŽธ Songsterr ็ฉถๆฅต (ใƒ—ใƒฌใƒŸใ‚ขใƒ ่งฃ้™ค) // @name:ko ๐ŸŽธ Songsterr ๊ถ๊ทน (ํ”„๋ฆฌ๋ฏธ์—„ ์–ธ๋ฝ) // @name:sv ๐ŸŽธ Songsterr Ultimat (Premium Upplรฅst) // @name:da ๐ŸŽธ Songsterr Ultimativ (Premium Lรฅst Op) // @namespace http://tampermonkey.net/ // @version 4.0.0 // @description Unlocks all Plus features (Speed, Loop, Solo, Mute, no pauses) + Native Export (.gp & .midi). (Tested on Zen Browser) // @description:fr Dรฉbloque toutes les fonctionnalitรฉs Plus (Vitesse, Loop, Solo, Mute, sans pauses) + Tรฉlรฉchargement natif (.gp & .midi). (Testรฉ sur Zen Browser) // @description:es Desbloquea todas las funciones Plus (Velocidad, Bucle, Solo, Mute, sin pausas) + Descarga nativa (.gp y .midi). (Probado en Zen Browser) // @description:de Schaltet alle Plus-Features frei (Geschwindigkeit, Loop, Solo, Mute, ohne Pausen) + Nativer Download (.gp & .midi). (Getestet auf Zen Browser) // @description:it Sblocca tutte le funzioni Plus (Velocitร , Loop, Solo, Mute, senza pause) + Download nativo (.gp e .midi). (Testato su Zen Browser) // @description:pt Desbloqueia todos os recursos Plus (Velocidade, Loop, Solo, Mute, sem pausas) + Download nativo (.gp e .midi). (Testado no Zen Browser) // @description:pt-BR Desbloqueia tudo do Plus (Velocidade, Loop, Solo, Mute, sem pausas) + Export nativo (.gp & .midi). (Testado no Zen Browser) // @description:nl Ontgrendelt alle Plus-functies (Snelheid, Loop, Solo, Mute, geen pauzes) + Native download (.gp & .midi). (Getest op Zen Browser) // @description:pl Odblokowuje wszystkie funkcje Plus (Prฤ™dkoล›ฤ‡, Pฤ™tla, Solo, Mute, bez przerw) + Natywny eksport (.gp i .midi). (Testowane na Zen Browser) // @description:ru ะ ะฐะทะฑะปะพะบะธั€ัƒะตั‚ ะฒัะต ั„ัƒะฝะบั†ะธะธ Plus (ะกะบะพั€ะพัั‚ัŒ, ะŸะตั‚ะปั, ะกะพะปะพ, Mute, ะฑะตะท ะฟะฐัƒะท) + ะะฐั‚ะธะฒะฝั‹ะน ัะบัะฟะพั€ั‚ (.gp ะธ .midi). (ะŸั€ะพั‚ะตัั‚ะธั€ะพะฒะฐะฝะพ ะฒ Zen Browser) // @description:ja Plusใฎๅ…จๆฉŸ่ƒฝ๏ผˆ้€Ÿๅบฆใ€ใƒซใƒผใƒ—ใ€ใ‚ฝใƒญใ€ใƒŸใƒฅใƒผใƒˆใ€็„กๅœๆญข๏ผ‰ใ‚’่งฃ้™ค + ใƒใ‚คใƒ†ใ‚ฃใƒ–ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰๏ผˆ.gp & .midi๏ผ‰ใ€‚(Zen Browserใงใƒ†ใ‚นใƒˆๆธˆใฟ) // @description:ko ๋ชจ๋“  Plus ๊ธฐ๋Šฅ ํ•ด์ œ (์†๋„, ๋ฃจํ”„, ์†”๋กœ, ๋ฎคํŠธ, ๋ฉˆ์ถค ์—†์Œ) + ๋„ค์ดํ‹ฐ๋ธŒ ๋‹ค์šด๋กœ๋“œ (.gp & .midi). (Zen Browser์—์„œ ํ…Œ์ŠคํŠธ๋จ) // @description:sv Lรฅser upp alla Plus-funktioner (Hastighet, Loop, Solo, Mute, inga pauser) + Naturlig export (.gp & .midi). (Testat pรฅ Zen Browser) // @description:da Lรฅser alle Plus-funktioner op (Hastighed, Loop, Solo, Mute, ingen pauser) + Naturlig download (.gp & .midi). (Testet pรฅ Zen Browser) // @author Goulagman // @supportURL https://github.com/GoulagmanYt/Songsterr-Plus-Ultimate-Unlocker- // @match *://www.songsterr.com/* // @require https://cdn.jsdelivr.net/npm/@coderline/alphatab@1.8.1/dist/alphaTab.min.js // @connect dqsljvtekg760.cloudfront.net // @connect d3d3l6a6rcgkaf.cloudfront.net // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_addStyle // @run-at document-start // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // LOGGING SYSTEM with Toggle // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• const LOG_KEY = 'songsterr_debug_logging'; let loggingEnabled = false; try { loggingEnabled = localStorage.getItem(LOG_KEY) === 'true'; } catch (e) {} // Wrapper for console logging - supports different prefixes function sgdLog(level, prefix, ...args) { if (!loggingEnabled) return; const fullPrefix = prefix ? `[${prefix}]` : '[SGD]'; if (level === 'error') console.error(fullPrefix, ...args); else if (level === 'warn') console.warn(fullPrefix, ...args); else console.log(fullPrefix, ...args); } // Toggle logging function window.toggleSgdLogging = function() { loggingEnabled = !loggingEnabled; try { localStorage.setItem(LOG_KEY, loggingEnabled); } catch (e) {} console.log(`๐ŸŽธ Songsterr Ultimate โ€” Logging ${loggingEnabled ? 'ENABLED' : 'DISABLED'}`); updateLogToggleUI(); }; // Update toggle button UI function updateLogToggleUI() { const btn = document.getElementById('sgd-log-toggle'); if (btn) { btn.innerHTML = `๐Ÿ“‹ Logging ${loggingEnabled ? 'ON' : 'OFF'}`; btn.title = loggingEnabled ? 'Debug logging enabled (click to disable)' : 'Debug logging disabled (click to enable)'; btn.classList.toggle('active', loggingEnabled); // Colors are handled by CSS classes (.active / :not(.active)) } } // Inject logging toggle into Gl5687 div function injectLogToggle() { const targetDiv = document.querySelector('.Gl5687'); if (!targetDiv || document.getElementById('sgd-log-toggle')) return; // Style the target div to allow centering targetDiv.style.cssText = ` display: flex !important; align-items: center !important; justify-content: center !important; width: 100% !important; height: 100% !important; `; const btn = document.createElement('button'); btn.id = 'sgd-log-toggle'; btn.className = 'sgd-log-toggle-btn'; btn.innerHTML = `๐Ÿ“‹ Logging ${loggingEnabled ? 'ON' : 'OFF'}`; btn.title = loggingEnabled ? 'Debug logging enabled (click to disable)' : 'Debug logging disabled (click to enable)'; btn.addEventListener('click', window.toggleSgdLogging); // Style the button - dark theme matching Songsterr btn.style.cssText = ` display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 8px 16px; border: 1px solid ${loggingEnabled ? '#16a34a' : '#dc2626'}; border-radius: 6px; background: ${loggingEnabled ? '#166534' : '#7f1d1d'}; color: #fff; font-size: 14px; font-weight: 500; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; cursor: pointer; transition: all 0.15s ease; min-width: 120px; height: 36px; `; btn.addEventListener('mouseenter', () => { btn.style.background = loggingEnabled ? '#15803d' : '#991b1b'; }); btn.addEventListener('mouseleave', () => { btn.style.background = loggingEnabled ? '#166534' : '#7f1d1d'; }); targetDiv.appendChild(btn); } // Watch for Gl5687 div to appear const logToggleObserver = new MutationObserver(() => { injectLogToggle(); }); logToggleObserver.observe(document.documentElement, { childList: true, subtree: true }); // Initial log console.log('๐ŸŽธ Songsterr Ultimate โ€” Active v4.0.0', loggingEnabled ? '(Debug logging ON)' : ''); // Replace all console.log throughout the script with sgdLog // (This will be done via find/replace in subsequent edits) // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // YOUTUBE AUDIO-ONLY SYSTEM (contribution ใƒ‘ใƒ—ใƒชใ‚ซ) // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• (function() { 'use strict'; // To avoid audio stopping issues (browser power-saving features, etc.), // we don't use display: none for parent elements either. Instead we use // size 0, transparency, and absolute positioning to completely // remove them from visual view while keeping them functional. const style = document.createElement('style'); style.id = 'paprika-yt-styles'; style.textContent = ` /* Hide iframe itself (exists in DOM, audio continues playing) */ .songsterr-yt-hidden-iframe { opacity: 0 !important; width: 0px !important; height: 0px !important; pointer-events: none !important; position: absolute !important; z-index: -9999 !important; border: none !important; } /* Hide iframe parent wrapper/background frame elements */ .songsterr-yt-hidden-wrapper { opacity: 0 !important; width: 0px !important; height: 0px !important; min-width: 0px !important; min-height: 0px !important; margin: 0 !important; padding: 0 !important; border: none !important; overflow: hidden !important; background: transparent !important; position: absolute !important; pointer-events: none !important; z-index: -9999 !important; } /* YouTube Audio-Only toggle button - dark theme */ #yt-toggle-btn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 6px; border: 1px solid #3a3a3a; background: #2a2a2a; color: #a5a5a5; cursor: pointer; font-size: 16px; transition: all 0.15s ease; } #yt-toggle-btn:hover { background: #3a3a3a; color: #e5e5e5; } #yt-toggle-btn.audio-only { background: #16a34a; color: #fff; border-color: #22c55e; } #yt-toggle-btn.audio-only:hover { background: #15803d; border-color: #16a34a; } `; if (document.head) { document.head.appendChild(style); } else { document.addEventListener('DOMContentLoaded', () => document.head.appendChild(style)); } // Audio-only mode state (persistent via localStorage) const YT_AUDIO_KEY = 'songsterr_yt_audio_only'; let ytAudioOnlyMode = false; try { ytAudioOnlyMode = localStorage.getItem(YT_AUDIO_KEY) === 'true'; } catch (e) {} /** * Function to detect and hide YouTube iframes and multi-level frames (black backgrounds, etc.) */ function hideYouTubeIframes() { if (!ytAudioOnlyMode) return; // Only hide if audio-only mode is activated const iframes = document.querySelectorAll('iframe'); const keywords = /(player|video|youtube)/i; iframes.forEach(iframe => { const src = iframe.src || ''; if (src.includes('youtube.com') || src.includes('youtu.be')) { if (!iframe.classList.contains('songsterr-yt-hidden-iframe')) { // 1. Make iframe itself invisible iframe.classList.add('songsterr-yt-hidden-iframe'); // 2. Process parent elements across multiple levels (up to 5 levels) let currentParent = iframe.parentElement; let level = 0; while (currentParent && level < 5) { // Stop when reaching body or html if (currentParent.tagName === 'BODY' || currentParent.tagName === 'HTML') { break; } const className = typeof currentParent.className === 'string' ? currentParent.className : ''; const idName = currentParent.id || ''; // Immediate wrappers (1-2 level parents) often have fixed size or black backgrounds, so hide unconditionally. // For higher levels (3-5 levels), hide only if class name or ID contains player/video/youtube etc. if (level < 2 || keywords.test(className) || keywords.test(idName)) { currentParent.classList.add('songsterr-yt-hidden-wrapper'); } currentParent = currentParent.parentElement; level++; } } } }); } // Function to show/hide iframes based on mode function updateYtVisibility() { if (ytAudioOnlyMode) { hideYouTubeIframes(); } else { // Video mode: remove hiding classes document.querySelectorAll('.songsterr-yt-hidden-iframe').forEach(el => { el.classList.remove('songsterr-yt-hidden-iframe'); }); document.querySelectorAll('.songsterr-yt-hidden-wrapper').forEach(el => { el.classList.remove('songsterr-yt-hidden-wrapper'); }); } // Update button const btn = document.getElementById('yt-toggle-btn'); if (btn) { btn.innerHTML = ytAudioOnlyMode ? '๐ŸŽต' : '๐ŸŽฌ'; btn.title = ytAudioOnlyMode ? 'Audio-only mode (click to show video)' : 'Video visible (click for audio-only)'; btn.classList.toggle('audio-only', ytAudioOnlyMode); } } // Expose toggle function globally window.toggleYtAudioOnly = function() { ytAudioOnlyMode = !ytAudioOnlyMode; try { localStorage.setItem(YT_AUDIO_KEY, ytAudioOnlyMode); } catch (e) {} updateYtVisibility(); }; // Initialize state hideYouTubeIframes(); // Setup MutationObserver to watch for DOM changes const observer = new MutationObserver((mutations) => { let shouldCheck = false; for (const mutation of mutations) { if (mutation.addedNodes.length > 0) { shouldCheck = true; break; } if (mutation.type === 'attributes' && mutation.target.tagName === 'IFRAME') { shouldCheck = true; break; } } if (shouldCheck) { hideYouTubeIframes(); } }); function startObserving() { if (!document.body) return; hideYouTubeIframes(); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] }); sgdLog('log', 'Songsterr YT Hider', 'Started monitoring (ใƒ‘ใƒ—ใƒชใ‚ซ็‰ˆ + toggle)'); } if (document.body) { startObserving(); } else { document.addEventListener('DOMContentLoaded', startObserving); } })(); // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // AUTOSCROLL FIX (contribution ใƒ‘ใƒ—ใƒชใ‚ซ) // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• (function() { 'use strict'; sgdLog('log', 'Songsterr Native Restore', 'Initializing native auto-scroll recovery...'); // ========================================== // 1. Disable CSS interference (restore scroll container) // ========================================== // SongsterrUltimate injects `body, html { overflow: auto !important; }` into