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