Create YouTube_Music_Auto_Confirm_-Are_You_Still_There-_&_Discretion_Warning-1.9.user.js
This commit is contained in:
@@ -0,0 +1,222 @@
|
|||||||
|
// ==UserScript==
|
||||||
|
// @name YouTube Music Auto Confirm "Are You Still There" & Discretion Warning
|
||||||
|
// @namespace http://tampermonkey.net/
|
||||||
|
// @version 1.9
|
||||||
|
// @description Prevents the "Video paused. Continue watching?" dialog from appearing, auto-clicks "Yes", and auto-accepts viewer discretion warnings.
|
||||||
|
// @author You
|
||||||
|
// @match https://music.youtube.com/*
|
||||||
|
// @grant none
|
||||||
|
// ==/UserScript==
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const CHECK_INTERVAL = 2000; // Fallback popup check interval
|
||||||
|
const ACTIVITY_SPOOF_INTERVAL = 60000; // 1 minute (Spoofs activity to prevent popup)
|
||||||
|
|
||||||
|
let spoofCount = 0;
|
||||||
|
let badgeElement = null;
|
||||||
|
let lastActionTime = 0; // Prevents rapid looping
|
||||||
|
|
||||||
|
// --- NEW: Native UI Integration & CSS Animations ---
|
||||||
|
|
||||||
|
function injectStyles() {
|
||||||
|
if (document.getElementById('ytm-anti-pause-styles')) return;
|
||||||
|
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'ytm-anti-pause-styles';
|
||||||
|
style.textContent = `
|
||||||
|
@keyframes ytm-anti-pause-pulse-dot {
|
||||||
|
0% { background-color: rgba(255, 255, 255, 0.5); box-shadow: 0 0 0px transparent; }
|
||||||
|
50% { background-color: #2ba640; box-shadow: 0 0 10px #2ba640; }
|
||||||
|
100% { background-color: rgba(255, 255, 255, 0.5); box-shadow: 0 0 0px transparent; }
|
||||||
|
}
|
||||||
|
@keyframes ytm-anti-pause-pulse-text {
|
||||||
|
0% { color: rgba(255, 255, 255, 0.5); }
|
||||||
|
50% { color: rgba(255, 255, 255, 0.9); }
|
||||||
|
100% { color: rgba(255, 255, 255, 0.5); }
|
||||||
|
}
|
||||||
|
.ytm-pulse-dot {
|
||||||
|
animation: ytm-anti-pause-pulse-dot 2s ease-in-out !important;
|
||||||
|
}
|
||||||
|
.ytm-pulse-text {
|
||||||
|
animation: ytm-anti-pause-pulse-text 2s ease-in-out !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVerificationBadge() {
|
||||||
|
if (badgeElement) return;
|
||||||
|
|
||||||
|
// Find the right side of the top navigation bar
|
||||||
|
const rightContent = document.querySelector('ytmusic-nav-bar #right-content');
|
||||||
|
|
||||||
|
if (!rightContent) {
|
||||||
|
// The page is still loading the nav bar, try again in 1 second
|
||||||
|
setTimeout(createVerificationBadge, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
injectStyles();
|
||||||
|
|
||||||
|
// Create the main container
|
||||||
|
badgeElement = document.createElement('div');
|
||||||
|
badgeElement.id = 'ytm-anti-pause-badge';
|
||||||
|
badgeElement.style.display = 'flex';
|
||||||
|
badgeElement.style.alignItems = 'center';
|
||||||
|
badgeElement.style.marginRight = '24px';
|
||||||
|
badgeElement.style.fontFamily = 'Roboto, Noto Naskh Arabic UI, Arial, sans-serif';
|
||||||
|
badgeElement.style.fontSize = '14px';
|
||||||
|
badgeElement.style.fontWeight = '500';
|
||||||
|
badgeElement.style.color = 'rgba(255, 255, 255, 0.5)';
|
||||||
|
badgeElement.style.cursor = 'default';
|
||||||
|
badgeElement.title = 'YouTube Music Anti-Pause is active';
|
||||||
|
|
||||||
|
// Create the pulsing status dot
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.id = 'ytm-anti-pause-dot';
|
||||||
|
dot.style.width = '6px';
|
||||||
|
dot.style.height = '6px';
|
||||||
|
dot.style.borderRadius = '50%';
|
||||||
|
dot.style.backgroundColor = 'rgba(255, 255, 255, 0.5)';
|
||||||
|
dot.style.marginRight = '8px';
|
||||||
|
|
||||||
|
// Create the text label
|
||||||
|
const text = document.createElement('span');
|
||||||
|
text.id = 'ytm-anti-pause-text';
|
||||||
|
text.innerText = `Anti-Pause: ${spoofCount}`;
|
||||||
|
|
||||||
|
badgeElement.appendChild(dot);
|
||||||
|
badgeElement.appendChild(text);
|
||||||
|
|
||||||
|
// Insert it at the beginning of the right-side icons
|
||||||
|
rightContent.insertBefore(badgeElement, rightContent.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBadgeDisplay() {
|
||||||
|
if (!badgeElement) return;
|
||||||
|
|
||||||
|
const text = badgeElement.querySelector('#ytm-anti-pause-text');
|
||||||
|
const dot = badgeElement.querySelector('#ytm-anti-pause-dot');
|
||||||
|
|
||||||
|
if (text) text.innerText = `Anti-Pause: ${spoofCount}`;
|
||||||
|
|
||||||
|
// Force a browser reflow to restart the CSS animation reliably
|
||||||
|
if (dot) {
|
||||||
|
dot.classList.remove('ytm-pulse-dot');
|
||||||
|
void dot.offsetWidth;
|
||||||
|
dot.classList.add('ytm-pulse-dot');
|
||||||
|
}
|
||||||
|
if (badgeElement) {
|
||||||
|
badgeElement.classList.remove('ytm-pulse-text');
|
||||||
|
void badgeElement.offsetWidth;
|
||||||
|
badgeElement.classList.add('ytm-pulse-text');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function spoofActivity(isInitial = false) {
|
||||||
|
// 1. Update YouTube's internal last activity tracker
|
||||||
|
window._lact = Date.now();
|
||||||
|
|
||||||
|
// 2. Dispatch a harmless background event to trigger any other listeners
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Shift', bubbles: true, cancelable: true }));
|
||||||
|
|
||||||
|
// 3. Update the verification badge (skip on initial load)
|
||||||
|
if (!isInitial) {
|
||||||
|
spoofCount++;
|
||||||
|
updateBadgeDisplay();
|
||||||
|
console.log(`[Auto-Confirm] Activity spoofed to prevent pause. (Count: ${spoofCount})`);
|
||||||
|
} else {
|
||||||
|
console.log(`[Auto-Confirm] Initial activity spoofed on load.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- EXISTING: Fallback Auto-Clicker ---
|
||||||
|
|
||||||
|
function dismissPopups() {
|
||||||
|
// Prevent spamming clicks and getting stuck in a play/pause loop
|
||||||
|
if (Date.now() - lastActionTime < 3000) return;
|
||||||
|
|
||||||
|
let actionTaken = false;
|
||||||
|
|
||||||
|
// 1. Check for "Are you still there?" dialog
|
||||||
|
const pausePopup = document.querySelector('ytmusic-you-there-renderer');
|
||||||
|
if (pausePopup && pausePopup.offsetParent !== null) {
|
||||||
|
const yesButton = pausePopup.querySelector('button[aria-label="Yes"]') ||
|
||||||
|
pausePopup.querySelector('button.yt-spec-button-shape-next');
|
||||||
|
|
||||||
|
if (yesButton && yesButton.offsetParent !== null) {
|
||||||
|
console.log('[Auto-Confirm] "Are you still there?" dialog detected. Clicking Yes.');
|
||||||
|
yesButton.click();
|
||||||
|
actionTaken = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
if (video && video.paused) {
|
||||||
|
console.log('[Auto-Confirm] Resuming video playback.');
|
||||||
|
const playPromise = video.play();
|
||||||
|
if (playPromise !== undefined) {
|
||||||
|
playPromise.catch(error => {
|
||||||
|
console.log('[Auto-Confirm] Autoplay prevented by browser:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Check for "Viewer discretion is advised" warning
|
||||||
|
const errorContainer = document.querySelector('#player-error-message-container');
|
||||||
|
if (errorContainer && errorContainer.offsetParent !== null) {
|
||||||
|
const proceedButton = errorContainer.querySelector('button[aria-label="I understand and wish to proceed"]');
|
||||||
|
|
||||||
|
if (proceedButton && proceedButton.offsetParent !== null) {
|
||||||
|
console.log('[Auto-Confirm] "Viewer discretion is advised" warning detected. Clicking Proceed.');
|
||||||
|
proceedButton.click();
|
||||||
|
actionTaken = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
if (video && video.paused) {
|
||||||
|
console.log('[Auto-Confirm] Resuming video playback after warning.');
|
||||||
|
const playPromise = video.play();
|
||||||
|
if (playPromise !== undefined) {
|
||||||
|
playPromise.catch(error => {
|
||||||
|
console.log('[Auto-Confirm] Autoplay prevented by browser:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000); // Give YT slightly more time to load the stream after clicking proceed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionTaken) {
|
||||||
|
lastActionTime = Date.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- INITIALIZATION ---
|
||||||
|
|
||||||
|
// Attempt to create the badge immediately (will retry if DOM isn't ready)
|
||||||
|
createVerificationBadge();
|
||||||
|
|
||||||
|
// Start the prevention loop
|
||||||
|
setInterval(() => spoofActivity(false), ACTIVITY_SPOOF_INTERVAL);
|
||||||
|
|
||||||
|
// Run it once immediately on load to set initial state (without incrementing counter)
|
||||||
|
spoofActivity(true);
|
||||||
|
|
||||||
|
// Start the fallback checking loop
|
||||||
|
setInterval(dismissPopups, CHECK_INTERVAL);
|
||||||
|
|
||||||
|
// Fallback: Listen for video pause events
|
||||||
|
document.addEventListener('pause', (event) => {
|
||||||
|
if (event.target && event.target.tagName === 'VIDEO') {
|
||||||
|
setTimeout(dismissPopups, 500);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
console.log('[Auto-Confirm] Script loaded. Prevention and monitoring active.');
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user