// ==UserScript==
// @name AniwatchTV - Player Isolation and Anti-Redirect
// @namespace https://aniwatchtv.to/
// @version 121.V121.Aniwatch.V3000
// @description Pauses all scripts except the video player on AniwatchTV and prevents redirects
// @author [NotYou](Gabriel Underwood)
// @match https://aniwatchtv.to/watch/*
// @match http://aniwatchtv.to/watch/*
// @grant unsafeWindow
// @run-at document-start
// @license MIT
// ==/UserScript==
(function() {
'use strict';
console.log('AniwatchTV Player Isolation Script initialized');
// Store original functions that we'll override
const originalSetTimeout = window.setTimeout;
const originalSetInterval = window.setInterval;
const originalRequestAnimationFrame = window.requestAnimationFrame;
const originalAddEventListener = EventTarget.prototype.addEventListener;
const originalPushState = History.prototype.pushState;
const originalReplaceState = History.prototype.replaceState;
const originalAssign = window.location.assign;
const originalReplace = window.location.replace;
const originalOpen = window.open;
// Known player elements based on provided HTML
const PLAYER_SELECTORS = [
'.player-frame',
'#iframe-embed',
'#embed-loading',
'.loading-relative',
'.loading-box'
];
// Track if we've found and protected the player
let playerProtected = false;
let redirectsPrevented = 0;
// Function to check if element is part of the video player
function isPlayerElement(element) {
if (!element) return false;
// Check if element matches our known player selectors
for (const selector of PLAYER_SELECTORS) {
if (element.matches && element.matches(selector)) {
return true;
}
// Check for specific ID
if (selector.startsWith('#') && element.id === selector.substring(1)) {
return true;
}
// Check for specific class
if (selector.startsWith('.') && element.classList &&
element.classList.contains(selector.substring(1))) {
return true;
}
}
// Check if element is the iframe with src containing player
if (element.tagName === 'IFRAME' && element.id === 'iframe-embed') {
return true;
}
// Check if it's a loading indicator for the player
if (element.classList &&
(element.classList.contains('loading') ||
element.classList.contains('loading-relative') ||
element.classList.contains('loading-box'))) {
return true;
}
// Check if it's a direct child of player-frame
if (element.parentElement &&
element.parentElement.classList &&
element.parentElement.classList.contains('player-frame')) {
return true;
}
return false;
}
// Check if element is part of the player or an ancestor of the player
function isPlayerOrAncestor(element) {
if (isPlayerElement(element)) return true;
// Check ancestors
let parent = element.parentElement;
while (parent) {
if (isPlayerElement(parent)) return true;
parent = parent.parentElement;
}
return false;
}
// Function to show notification
function showNotification(message, duration = 3000) {
if (!document.body) {
setTimeout(() => showNotification(message, duration), 100);
return;
}
let notification = document.getElementById('aniwatch-script-notification');
if (!notification) {
notification = document.createElement('div');
notification.id = 'aniwatch-script-notification';
notification.style.position = 'fixed';
notification.style.top = '20px';
notification.style.right = '20px';
notification.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
notification.style.color = 'white';
notification.style.padding = '12px 16px';
notification.style.borderRadius = '6px';
notification.style.zIndex = '9999999';
notification.style.fontFamily = 'Arial, sans-serif';
notification.style.fontSize = '14px';
notification.style.maxWidth = '300px';
notification.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
document.body.appendChild(notification);
}
notification.textContent = message;
notification.style.display = 'block';
// Hide after duration
setTimeout(() => {
notification.style.display = 'none';
}, duration);
}
// Block redirects to home page
function blockRedirectToHome(url) {
if (!url) return false;
try {
const urlObj = new URL(url, window.location.origin);
// Check if it's trying to redirect to homepage
if (urlObj.pathname === '/' ||
urlObj.pathname === '/home' ||
urlObj.pathname.toLowerCase().includes('home')) {
redirectsPrevented++;
return true; // Should block
}
} catch (e) {
// If URL parsing fails, be cautious and don't block
return false;
}
return false; // Don't block
}
// Override setTimeout to control script execution
window.setTimeout = function(callback, timeout, ...args) {
// If it's a string callback, check for problematic redirects
if (typeof callback === 'string') {
if (callback.includes('location') ||
callback.includes('redirect') ||
callback.includes('window.location')) {
return Math.floor(Math.random() * 10000); // Fake timeout ID
}
}
// For function callbacks, create a wrapper
if (typeof callback === 'function') {
const wrappedCallback = function() {
// Detect if this is executed in player context
const isPlayerContext = isPlayerOrAncestor(this);
// If it's player-related or we're in an iframe that's the player
if (isPlayerContext || window.self !== window.top) {
return callback.apply(this, args);
}
// Block potentially problematic callbacks
return null;
};
return originalSetTimeout.call(this, wrappedCallback, timeout);
}
return originalSetTimeout.apply(this, arguments);
};
// Override setInterval similar to setTimeout
window.setInterval = function(callback, timeout, ...args) {
// If it's a string callback, check for problematic redirects
if (typeof callback === 'string') {
if (callback.includes('location') ||
callback.includes('redirect') ||
callback.includes('window.location')) {
return Math.floor(Math.random() * 10000); // Fake interval ID
}
}
// For function callbacks, create a wrapper
if (typeof callback === 'function') {
const wrappedCallback = function() {
// Detect if this is executed in player context
const isPlayerContext = isPlayerOrAncestor(this);
// If it's player-related or we're in an iframe that's the player
if (isPlayerContext || window.self !== window.top) {
return callback.apply(this, args);
}
// Block potentially problematic callbacks
return null;
};
return originalSetInterval.call(this, wrappedCallback, timeout);
}
return originalSetInterval.apply(this, arguments);
};
// Override history methods to prevent navigation
History.prototype.pushState = function(state, title, url) {
if (blockRedirectToHome(url)) {
console.log('Blocked pushState redirect to:', url);
return;
}
return originalPushState.apply(this, arguments);
};
History.prototype.replaceState = function(state, title, url) {
if (blockRedirectToHome(url)) {
console.log('Blocked replaceState redirect to:', url);
return;
}
return originalReplaceState.apply(this, arguments);
};
// Override location methods
const originalLocationAssign = Location.prototype.assign;
Location.prototype.assign = function(url) {
if (blockRedirectToHome(url)) {
console.log('Blocked location.assign redirect to:', url);
return;
}
return originalLocationAssign.call(this, url);
};
const originalLocationReplace = Location.prototype.replace;
Location.prototype.replace = function(url) {
if (blockRedirectToHome(url)) {
console.log('Blocked location.replace redirect to:', url);
return;
}
return originalLocationReplace.call(this, url);
};
// Override window.open
window.open = function(url) {
if (url && typeof url === 'string' && url.includes('home')) {
console.log('Blocked window.open redirect to:', url);
redirectsPrevented++;
return null;
}
return originalOpen.apply(this, arguments);
};
// Block setting location directly
Object.defineProperty(window, 'location', {
get: function() {
return window.location;
},
set: function(url) {
if (typeof url === 'string' && url.includes('home')) {
console.log('Blocked direct location change to:', url);
redirectsPrevented++;
return window.location;
}
window.location.href = url;
return window.location;
}
});
// Find and protect the player once DOM is ready
function findAndProtectPlayer() {
console.log('Looking for video player to protect...');
// Specifically look for the player elements from the provided HTML
const playerFrame = document.querySelector('.player-frame');
const iframe = document.querySelector('#iframe-embed');
if (playerFrame && iframe) {
console.log('Found player elements to protect');
playerProtected = true;
// Make sure iframe src is properly set if empty
if (!iframe.src || iframe.src === '') {
// Try to find the correct source from page data
// This is a common pattern where the iframe src is set by JS
const scriptTags = document.querySelectorAll('script:not([src])');
let possibleSrc = '';
scriptTags.forEach(script => {
const content = script.textContent;
if (content.includes('iframe-embed') && content.includes('src')) {
const match = content.match(/["']iframe-embed["']\.src\s*=\s*["']([^"']+)["']/);
if (match && match[1]) {
possibleSrc = match[1];
}
}
});
if (possibleSrc) {
console.log('Setting iframe src to:', possibleSrc);
iframe.src = possibleSrc;
}
}
// Enhance player visibility
playerFrame.style.zIndex = '9999';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.minHeight = '500px';
iframe.setAttribute('allowfullscreen', 'true');
showNotification('Player protected. Blocking all other scripts.', 5000);
} else {
console.log('Player elements not found yet');
// If not found, try again in a moment
setTimeout(findAndProtectPlayer, 500);
}
}
// Add style to hide annoying elements and ensure player visibility
function addStyles() {
const style = document.createElement('style');
style.textContent = `
/* Hide potential ad elements */
div[class*="ads"], div[id*="ads"],
div[class*="ad-"], div[id*="ad-"],
div[class*="-ad"], div[id*="-ad"],
div[class*="banner"], div[id*="banner"],
div[class*="popup"], div[id*="popup"] {
display: none !important;
}
/* Make sure player is visible */
.player-frame {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
position: relative !important;
z-index: 9999 !important;
min-height: 500px !important;
}
#iframe-embed {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
width: 100% !important;
height: 100% !important;
min-height: 500px !important;
}
`;
// Add style to head
const head = document.head || document.getElementsByTagName('head')[0];
if (head) {
head.appendChild(style);
} else {
// If head isn't available yet, wait and try again
setTimeout(addStyles, 100);
}
}
// Monitor status and display periodic updates
function startStatusMonitor() {
setInterval(() => {
if (redirectsPrevented > 0) {
showNotification(`Prevented ${redirectsPrevented} redirect attempts`);
redirectsPrevented = 0;
}
}, 10000);
}
// Initialize everything
function initialize() {
// Add styles immediately
addStyles();
// Start finding and protecting player once DOM starts loading
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', findAndProtectPlayer);
} else {
findAndProtectPlayer();
}
// Start status monitor
startStatusMonitor();
console.log('AniwatchTV Player Isolation Script fully initialized');
}
// Execute initialization
initialize();
})();