您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto-click navigation button when enabled, auto-play videos
// ==UserScript== // @name IDriveSafely.com auto skip // @namespace auto clicker // @version 4.2 // @description Auto-click navigation button when enabled, auto-play videos // @author 💩p💩o💩o // @match https://app.idrivesafely.com/* // @license MIT // ==/UserScript== (function() { 'use strict'; console.log("IDriveSafely Auto Skip Script Started v4.2"); let videoPlayed = false; let continueLearningButtonClicked = false; let lastButtonState = null; let lastUrl = window.location.href; // Function to check if an element appears disabled in any way function isButtonDisabled(button) { if (!button) return true; // Check standard disabled property if (button.disabled) return true; // Check disabled attribute if (button.hasAttribute('disabled')) return true; // Check aria-disabled if (button.getAttribute('aria-disabled') === 'true') return true; // Check for disabled class const classList = button.className || ''; if (classList.includes('disabled') || classList.includes('btn-disabled')) return true; // Check if button has opacity suggesting it's disabled const computedStyle = window.getComputedStyle(button); if (computedStyle.opacity < 0.5) return true; // Check if button has pointer-events: none if (computedStyle.pointerEvents === 'none') return true; // Check parent elements for disabled state let parent = button.parentElement; while (parent && parent !== document.body) { if (parent.classList && parent.classList.contains('disabled')) return true; parent = parent.parentElement; } return false; } // Function to check if any video is playing function isVideoPlaying() { const videos = document.querySelectorAll('video'); for (const video of videos) { if (video && !video.paused && video.currentTime > 0) { return true; } } return false; } // Function to auto-play video function autoPlayVideo() { if (videoPlayed || isVideoPlaying()) { if (!videoPlayed && isVideoPlaying()) { console.log("Video is already playing"); videoPlayed = true; } return; } // Try to find and play video directly const videoElements = document.querySelectorAll('video'); for (const video of videoElements) { if (video && video.paused && video.readyState >= 2) { console.log("Found video element - attempting to play directly"); video.play().then(() => { console.log("Video started playing successfully"); videoPlayed = true; }).catch(err => { console.log("Direct video play failed:", err.message); // Don't set videoPlayed = true here, let other methods try }); // Give direct play a chance before trying other methods return; } } // Wait a bit before trying click methods to allow direct play attempt to complete setTimeout(() => { if (isVideoPlaying()) { videoPlayed = true; return; } // Try clicking the video poster (most reliable based on user feedback) const videoPoster = document.querySelector('.vjs-poster'); if (videoPoster) { console.log("Video poster found - clicking to trigger playback"); videoPoster.click(); // Check if video started after a short delay setTimeout(() => { if (isVideoPlaying()) { console.log("Video started after poster click"); videoPlayed = true; } }, 500); return; } // Try clicking the video container div (since clicking anywhere works) const videoContainer = document.querySelector('[data-vjs-player="true"]') || document.querySelector('.video-js'); if (videoContainer) { console.log("Video container found - clicking to trigger playback"); // Try to simulate user interaction more thoroughly videoContainer.focus(); // Create and dispatch a click event const clickEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: true, buttons: 1 }); videoContainer.dispatchEvent(clickEvent); // Also try direct click videoContainer.click(); // Check if video started after a short delay setTimeout(() => { if (isVideoPlaying()) { console.log("Video started after container click"); videoPlayed = true; } }, 500); return; } // Try clicking the custom play button const customPlayButton = document.querySelector('[data-test="playButton"]'); if (customPlayButton && !isButtonDisabled(customPlayButton)) { console.log("Custom Play button found - clicking!"); customPlayButton.click(); setTimeout(() => { if (isVideoPlaying()) { console.log("Video started after play button click"); videoPlayed = true; } }, 500); return; } // Try clicking the Video.js play button const vjsPlayButton = document.querySelector('.vjs-big-play-button'); if (vjsPlayButton && !isButtonDisabled(vjsPlayButton)) { console.log("Video.js Play button found - clicking!"); vjsPlayButton.click(); setTimeout(() => { if (isVideoPlaying()) { console.log("Video started after Video.js button click"); videoPlayed = true; } }, 500); return; } // Try the original play button selector const playButton = document.querySelector('[title="Play Video"]'); if (playButton && !isButtonDisabled(playButton)) { console.log("Play Video button found - clicking!"); playButton.click(); setTimeout(() => { if (isVideoPlaying()) { console.log("Video started after play button click"); videoPlayed = true; } }, 500); return; } }, 300); } // Function to check if we're on a video page function isVideoPage() { return document.querySelector('.gritCourseflowNode--video') !== null || document.querySelector('video') !== null || document.querySelector('.video-js') !== null; } // Function to reset state when page changes function checkPageChange() { if (window.location.href !== lastUrl) { console.log("Page changed - resetting state"); videoPlayed = false; continueLearningButtonClicked = false; lastButtonState = null; lastUrl = window.location.href; } } // Main function to handle button clicks function clickButtons() { // Check if page changed checkPageChange(); console.log("Checking for buttons and videos..."); // Check for continue learning button first if (!continueLearningButtonClicked) { const continueButton = document.querySelector('[data-test="continueLearningButton"]'); if (continueButton && !isButtonDisabled(continueButton)) { console.log("Continue Learning button found and enabled - clicking!"); continueButton.click(); continueLearningButtonClicked = true; } } // Check if we're on a video page and auto-play if needed if (isVideoPage()) { autoPlayVideo(); } // Check for navigation arrow button const arrowButton = document.querySelector('#arrow-next') || document.querySelector('[data-test="courseflow-forward"]') || document.querySelector('button[id*="arrow"]') || document.querySelector('button[class*="arrow"]'); if (arrowButton) { const isDisabled = isButtonDisabled(arrowButton); // Log state change if (lastButtonState !== isDisabled) { console.log(`Navigation button state changed: ${isDisabled ? 'DISABLED' : 'ENABLED'}`); lastButtonState = isDisabled; } if (!isDisabled) { console.log("Navigation button is ENABLED - clicking!"); arrowButton.click(); // Reset flags after navigation videoPlayed = false; continueLearningButtonClicked = false; console.log("Button clicked! Flags reset."); } else { console.log("Navigation button is disabled - waiting..."); } } else { console.log("No navigation button found on page"); } } // Add mutation observer to detect when video elements are added to the page const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === 'childList') { // Check if video elements were added const addedVideos = Array.from(mutation.addedNodes).some(node => node.nodeName === 'VIDEO' || (node.querySelector && node.querySelector('video')) ); if (addedVideos && !videoPlayed) { console.log("New video element detected"); setTimeout(autoPlayVideo, 1000); // Give it more time to fully load } } } }); // Start observing the document for changes observer.observe(document.body, { childList: true, subtree: true }); // Run immediately on load with a longer delay setTimeout(clickButtons, 2000); // Then run every 2 seconds (faster than original but not too aggressive) setInterval(clickButtons, 2000); console.log("Script initialized - checking buttons and videos every 2 seconds"); })();