// Configurable Settings const OUTRO_SKIP_THRESHOLD = 110; // Time in seconds remaining to skip at the outro const SKIP_FORWARD_TIME = 90; // Time in seconds to skip forward when 'V' is pressed const VIDEO_PLAYER = "brittneystandardwestern.com"; // ==UserScript== // @name Aniworld.to Autoplay // @namespace http://tampermonkey.net/ // @version 4.20 // @description Autoplay for aniworld // @match *://aniworld.to/* // @match *://brittneystandardwestern.com/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; // Load skip state from localStorage, default to true if not set let skipToNextEpisodeEnabled = JSON.parse(localStorage.getItem('skipToNextEpisodeEnabled')) ?? true; function toggleSkipToNextEpisode() { skipToNextEpisodeEnabled = !skipToNextEpisodeEnabled; localStorage.setItem('skipToNextEpisodeEnabled', JSON.stringify(skipToNextEpisodeEnabled)); const toggleButton = document.querySelector('.skip-toggle-button .Autoplay-button'); const tooltip = document.querySelector('.skip-toggle-button .plyr__tooltip'); if (toggleButton && tooltip) { updateToggleSwitch(toggleButton, tooltip); } } // add skip button function addSkipToggleButton() { const controls = document.querySelector('.plyr__controls'); if (controls) { const button = document.createElement('button'); button.classList.add('plyr__controls__item', 'plyr__control', 'skip-toggle-button', 'Autoplay-button'); button.type = 'button'; button.setAttribute('aria-label', skipToNextEpisodeEnabled ? 'Disable skip to next episode' : 'Enable skip to next episode'); const toggleContainer = document.createElement('div'); toggleContainer.classList.add('Autoplay-button-container'); const toggleSwitch = document.createElement('div'); toggleSwitch.classList.add('Autoplay-button'); toggleSwitch.setAttribute('aria-checked', skipToNextEpisodeEnabled.toString()); const tooltip = document.createElement('span'); tooltip.classList.add('plyr__tooltip'); tooltip.textContent = skipToNextEpisodeEnabled ? 'Autoplay is enabled' : 'Autoplay is disabled'; toggleContainer.appendChild(toggleSwitch); button.appendChild(toggleContainer); button.appendChild(tooltip); button.addEventListener('click', toggleSkipToNextEpisode); controls.insertBefore(button, controls.lastChild); updateToggleSwitch(toggleSwitch, tooltip); } } function updateToggleSwitch(toggleSwitch, tooltip) { if (skipToNextEpisodeEnabled) { toggleSwitch.style.backgroundColor = '#ffffff'; toggleSwitch.style.transform = 'translateX(12px)'; tooltip.textContent = 'Autoplay On'; } else { toggleSwitch.style.backgroundColor = '#bbb'; toggleSwitch.style.transform = 'translateX(0px)'; tooltip.textContent = 'Autoplay Off'; } } // Press the play button function playVideo() { if (!skipToNextEpisodeEnabled) return; const playButton = document.querySelector('button.plyr__controls__item.plyr__control[data-plyr="play"]'); if (playButton) { playButton.click(); console.log("Play button clicked."); } else { console.log("Play button not found."); } } function skipForward() { const video = document.querySelector('video'); if (video) { video.currentTime = Math.min(video.currentTime + SKIP_FORWARD_TIME, video.duration); } else { console.error("Video element not found for skipping"); } } function checkAndPostMessage() { if (skipToNextEpisodeEnabled) { const video = document.querySelector('video'); if (video) { if (video.duration - video.currentTime <= OUTRO_SKIP_THRESHOLD) { window.parent.postMessage({ action: 'skipToNextEpisode' }, '*'); } } } } function getNextEpisodeUrl() { const currentEpisodeUrl = window.location.href; const episodeMatch = currentEpisodeUrl.match(/\/episode-(\d+)/); if (episodeMatch && episodeMatch[1]) { const currentEpisodeNumber = parseInt(episodeMatch[1], 10); const episodeLinks = Array.from(document.querySelectorAll('ul li a[data-episode-id]')); const totalEpisodes = episodeLinks.length; if (currentEpisodeNumber < totalEpisodes) { const nextEpisodeNumber = currentEpisodeNumber + 1; return currentEpisodeUrl.replace(/\/episode-\d+/, `/episode-${nextEpisodeNumber}`); } else { const currentSeasonMatch = currentEpisodeUrl.match(/\/staffel-(\d+)\//); if (currentSeasonMatch && currentSeasonMatch[1]) { const currentSeason = parseInt(currentSeasonMatch[1], 10); const nextSeason = currentSeason + 1; return currentEpisodeUrl.replace(/\/staffel-\d+\/episode-\d+/, `/staffel-${nextSeason}/episode-1`); } } } return null; } // Function to send play message function sendPlayMessage() { if (!skipToNextEpisodeEnabled) return; const iframe = document.querySelector(`iframe[src*="${VIDEO_PLAYER}"]`); if (iframe) { iframe.contentWindow.postMessage({ action: 'play' }, '*'); } } // Behavior for Video Player if (window.location.hostname === VIDEO_PLAYER) { setInterval(checkAndPostMessage, 5000); window.addEventListener("message", function (event) { if (event.data.action === "play") { playVideo(); } }); window.addEventListener('load', function () { if (skipToNextEpisodeEnabled) { playVideo(); } }); window.addEventListener('keydown', function (event) { if ((event.key === 'V' || event.key === 'v') && !event.target.closest('input, textarea')) { skipForward(); } }); } // Behavior for aniworld.to if (window.location.hostname === "aniworld.to") { window.addEventListener('message', function (event) { if (event.origin.includes(VIDEO_PLAYER) && event.data.action === 'skipToNextEpisode') { const nextEpisodeUrl = getNextEpisodeUrl(); if (nextEpisodeUrl) { window.location.href = nextEpisodeUrl; if (skipToNextEpisodeEnabled) { setTimeout(sendPlayMessage, 2000); } } else { console.error("Next episode URL could not be determined."); } } }); window.addEventListener('load', function () { if (skipToNextEpisodeEnabled) { sendPlayMessage(); } }); } // Autoplay button Style const style = document.createElement('style'); style.textContent = ` .Autoplay-button-container { width: 24px; height: 12px; background-color: rgba(221, 221, 221, 0.5); border-radius: 6px; position: absolute; top: 50%; transform: translateY(-50%); right: -4px; cursor: pointer; display: inline-block; z-index: 10; } .Autoplay-button { width: 12px; height: 12px; background-color: #bbb; border-radius: 50%; position: absolute; top: 0; left: 0; transition: all 0.2s ease; } .Autoplay-button[aria-checked="true"] { background-color: #ffffff; transform: translateX(12px); } .plyr__tooltip { position: absolute; bottom: 35px; left: 50%; transform: translateX(-50%); padding: 4px 8px; background: rgba(0, 0, 0, 0.75); color: #fff; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; transition: opacity 0.2s ease; pointer-events: none; } .skip-toggle-button:hover .plyr__tooltip { opacity: 1; } `; document.head.appendChild(style); window.addEventListener('load', function () { addSkipToggleButton(); }); })();