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-load
// @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();
    };
})();