Greasy Fork

来自缓存

Greasy Fork is available in English.

Super Fast Load

Optimize fast loading, prevent autoplay, add youtube download button, lazy load media, boost speed, and block tracking.

当前为 2024-11-27 提交的版本,查看 最新版本

// ==UserScript==
// @name         Super Fast Load
// @namespace    http://greasyfork.icu/en/scripts/517138-super-fast-loading
// @version      1.8
// @description  Optimize fast loading, prevent autoplay, add youtube download button, lazy load media, boost speed, and block tracking.
// @author
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    const CONFIG = {
        resourceCache: new Set(),
        optimizationUrls: ['https://example1.com/resource.js', 'https://example2.com/styles.css'],
        blockList: ['ads.example.com', 'tracking.example.com'],
        nonEssentialSelectors: ['script[src*="tracking"]', 'iframe[src*="advertisement"]', '.ad-banner', '.cookie-consent'],
        criticalResources: ['https://example.com/styles.css', 'https://example.com/script.js'],
        concurrentConnections: 4,
        timeout: 10000,
    };

    class Utilities {
        static async fetchWithTimeout(url, options = {}) {
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), CONFIG.timeout);
            try {
                const response = await fetch(url, { ...options, signal: controller.signal });
                clearTimeout(timeoutId);
                return response;
            } catch (error) {
                clearTimeout(timeoutId);
                throw error;
            }
        }

        static injectCSS(css) {
            const style = document.createElement('style');
            style.textContent = css;
            document.head.appendChild(style);
        }

        static chunkArray(array, size) {
            return Array.from({ length: Math.ceil(array.length / size) }, (_, index) =>
                array.slice(index * size, (index + 1) * size)
            );
        }

        static preloadLinks() {
            const links = document.querySelectorAll('a[href]');
            links.forEach(link => {
                const url = link.href;
                if (!CONFIG.resourceCache.has(url)) {
                    const linkElement = document.createElement('link');
                    linkElement.rel = 'prefetch';
                    linkElement.href = url;
                    document.head.appendChild(linkElement);
                    CONFIG.resourceCache.add(url);
                }
            });
        }
    }

    class ResourceManager {
        static async loadWithMultipleConnections(url) {
            if (CONFIG.resourceCache.has(url)) return null;
            try {
                const response = await Utilities.fetchWithTimeout(url, { cache: 'force-cache', mode: 'no-cors' });
                if (!response.ok) throw new Error('Network response was not ok');
                const blob = await response.blob();
                CONFIG.resourceCache.add(url);
                return URL.createObjectURL(blob);
            } catch (error) {
                console.error('Download error:', error);
                return null;
            }
        }

        static async loadResource(url, type) {
            const blobUrl = await this.loadWithMultipleConnections(url);
            if (!blobUrl) return;
            const element = document.createElement(type === 'css' ? 'link' : 'script');
            element[type === 'css' ? 'href' : 'src'] = blobUrl;
            element.rel = type === 'css' ? 'stylesheet' : undefined;
            element.defer = type !== 'css';
            document.head.appendChild(element);
        }

        static preloadResources() {
            const resources = [...CONFIG.criticalResources, ...CONFIG.optimizationUrls];
            const chunks = Utilities.chunkArray(resources, CONFIG.concurrentConnections);
            chunks.forEach(chunk => {
                chunk.forEach(resource => {
                    this.loadResource(resource, resource.endsWith('.css') ? 'css' : 'js');
                });
            });
        }
    }

    class SecurityEnhancer {
        static blockUnnecessaryRequests() {
            const originalOpen = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function(method, url, ...args) {
                if (CONFIG.blockList.some(domain => url.includes(domain))) {
                    console.log(`Blocked request to: ${url}`);
                    return;
                }
                return originalOpen.call(this, method, url, ...args);
            };
        }

        static preventDataCollection() {
            navigator.geolocation.getCurrentPosition = () => console.warn("Geolocation access blocked.");
            Object.defineProperty(navigator, 'userAgent', { get: () => 'Blocked User Agent' });
        }

        static removeNonEssentialElements() {
            CONFIG.nonEssentialSelectors.forEach(selector => {
                document.querySelectorAll(selector).forEach(element => element.remove());
            });
        }
    }

    class MediaOptimizer {
        static preventAutoplay() {
            const stopAutoplay = (media) => {
                media.pause();
                media.preload = 'none';
                media.autoplay = false;
                media.setAttribute('data-autoplay-prevented', 'true');

                media.addEventListener('click', () => {
                    if (media.paused) {
                        media.play();
                    } else {
                        media.pause();
                    }
                });

                // Remove default controls
                media.controls = false;

                // حذف دکمه خاکستری پلی
                const playButton = document.querySelector('.ytp-large-play-button, .ytp-small-play-button');
                if (playButton) {
                    playButton.remove();
                }
            };

            // Initial prevention
            document.querySelectorAll('video, audio').forEach(stopAutoplay);

            // Observe for dynamically added media elements
            const observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    if (mutation.type === 'childList') {
                        mutation.addedNodes.forEach((node) => {
                            if (node.nodeName === 'VIDEO' || node.nodeName === 'AUDIO') {
                                stopAutoplay(node);
                            } else if (node.querySelectorAll) {
                                node.querySelectorAll('video, audio').forEach(stopAutoplay);
                            }
                        });
                    }
                });
            });

            observer.observe(document.body, { childList: true, subtree: true });
        }

        static lazyLoadMedia() {
            const observer = new IntersectionObserver(entries => {
                entries.forEach(async entry => {
                    if (entry.isIntersecting) {
                        const media = entry.target;
                        const blobUrl = await ResourceManager.loadWithMultipleConnections(media.dataset.src);
                        if (blobUrl) {
                            media.src = blobUrl;
                            observer.unobserve(media);
                        }
                    }
                });
            }, { threshold: 0.1, rootMargin: '200px' });

            document.querySelectorAll('video[data-src], audio[data-src], img[data-src]').forEach(media => observer.observe(media));
        }

        static enableLazyLoadImages() {
            document.querySelectorAll('img:not([loading])').forEach(img => {
                img.loading = 'lazy';
                img.decoding = 'async';
                img.referrerPolicy = 'no-referrer';
            });
        }
    }

    class YouTubeEnhancer {
        static createDownloadButton() {
            const downloadButton = document.createElement('button');
            downloadButton.id = 'custom-download-button';
            downloadButton.textContent = 'VIDEO DOWNLOAD';
            downloadButton.onclick = this.showModal;

            const interval = setInterval(() => {
                const controls = document.querySelector('.ytp-right-controls');
                if (controls && !document.getElementById('custom-download-button')) {
                    controls.insertBefore(downloadButton, controls.firstChild);
                    clearInterval(interval);
                }
            }, 1000);
        }

        static showModal() {
            const overlay = document.createElement('div');
            overlay.id = 'modal-overlay';
            overlay.onclick = YouTubeEnhancer.hideModal;

            const modalContent = document.createElement('div');
            modalContent.id = 'modal-content';

            const iframe = document.createElement('iframe');
            const videoID = new URLSearchParams(window.location.search).get('v');
            if (videoID) {
                iframe.src = `https://www.y2mate.com/youtube/${videoID}`;
            }
            modalContent.appendChild(iframe);
            overlay.appendChild(modalContent);
            document.body.appendChild(overlay);

            overlay.style.display = 'flex';
        }

        static hideModal() {
            document.getElementById('modal-overlay')?.remove();
        }
    }

    function optimizePerformance() {
        requestIdleCallback(() => {
            SecurityEnhancer.blockUnnecessaryRequests();
            SecurityEnhancer.preventDataCollection();
            MediaOptimizer.lazyLoadMedia();
            MediaOptimizer.enableLazyLoadImages();
            ResourceManager.preloadResources();
            SecurityEnhancer.removeNonEssentialElements();
            Utilities.preloadLinks();  // Preload links for faster navigation
        });
    }

    Utilities.injectCSS(`
        #custom-download-button {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #3399ff;
            color: white;
            border: none;
            padding: 10px 28px;
            border-radius: 25px;
            font-size: 14px;
            cursor: pointer;
            z-index: 1000;
        }

        #modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 2000;
        }

        #modal-content {
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            width: 80%;
            max-width: 600px;
        }

        #modal-content iframe {
            width: 100%;
            height: 400px;
            border: none;
        }

        /* Hide the large play button */
        .ytp-large-play-button {
            display: none !important;
        }

        /* Hide the small play button that appears in some videos */
        .ytp-small-play-button {
            display: none !important;
        }

        /* Hide the default play button */
        video::-webkit-media-controls {
            display: none !important;
        }

        /* ... سایر استایل‌ها ... */
    `);

    window.addEventListener('yt-navigate-finish', () => {
        MediaOptimizer.preventAutoplay();
        YouTubeEnhancer.createDownloadButton();
    });

    window.addEventListener('load', () => {
        MediaOptimizer.preventAutoplay();
        YouTubeEnhancer.createDownloadButton();
        optimizePerformance();
    });

    // Ensure autoplay prevention works even for dynamically loaded content
    const originalPushState = history.pushState;
    history.pushState = function() {
        originalPushState.apply(this, arguments);
        MediaOptimizer.preventAutoplay();
    };

    const originalReplaceState = history.replaceState;
    history.replaceState = function() {
        originalReplaceState.apply(this, arguments);
        MediaOptimizer.preventAutoplay();
    };
})();