您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Manual image replacement for Fortnite.gg with enhanced error handling
// ==UserScript== // @name Fortnite Image Replacer // @version 1.11 // @description Manual image replacement for Fortnite.gg with enhanced error handling // @match https://fortnite.gg/* // @grant none // @namespace https://greasyfork.org/users/789838 // ==/UserScript== (function() { 'use strict'; // Использование строгого режима JavaScript // Прозрачный пиксель в формате base64, используется как fallback const TRANSPARENT_PIXEL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; // Функция для проверки доступности изображения по URL function checkImage(url, callback) { const img = new Image(); img.onload = () => callback(true); // Изображение загружено успешно img.onerror = () => callback(false); // Ошибка загрузки изображения img.src = url + '?t=' + Date.now(); // Добавление timestamp для избежания кеширования } // Функция для захвата кадра из видео function captureVideoFrame(videoUrl, callback) { const video = document.createElement('video'); video.crossOrigin = 'anonymous'; // Разрешение кросс-доменных запросов let attempts = 0; // Счетчик попыток захвата кадра // Функция для очистки ресурсов const cleanup = () => { video.removeEventListener('loadeddata', onLoaded); video.removeEventListener('seeked', onSeeked); video.removeEventListener('error', onError); video.remove(); }; // Обработчик события загрузки метаданных видео const onLoaded = () => { if (video.duration === Infinity || video.duration < 2) { video.currentTime = Math.min(0.01, video.duration || 0.01); return; } video.currentTime = 2; // Перемотка на 2 секунду для захвата кадра }; // Обработчик события завершения перемотки видео const onSeeked = () => { try { if (video.readyState < 2) return; // Создание canvas для рендеринга кадра видео const canvas = document.createElement('canvas'); canvas.width = video.videoWidth || 800; canvas.height = video.videoHeight || 450; const ctx = canvas.getContext('2d'); ctx.drawImage(video, 0, 0, canvas.width, canvas.height); callback(canvas.toDataURL()); // Возврат кадра в формате data URL cleanup(); } catch (e) { handleVideoError(e); } }; // Обработчик ошибок при работе с видео const handleVideoError = (e) => { if (attempts++ < 2) { video.currentTime = 0.01; // Повторная попытка с другим временем return; } console.error('Video capture failed:', e); callback(null); // Возврат null при неудаче cleanup(); }; const onError = (e) => { handleVideoError(e); }; // Подписка на события видео video.addEventListener('loadeddata', onLoaded); video.addEventListener('seeked', onSeeked); video.addEventListener('error', onError); video.src = videoUrl; } // Основная функция замены изображений function replaceImages() { // Поиск всех изображений с классами или атрибутами, содержащими путь к изображениям предметов const images = document.querySelectorAll('.img, img[src*="/img/items/"]'); images.forEach((image) => { const originalSrc = image.src || image.getAttribute('data-src'); if (!originalSrc) return; // Обработка изображений из раздела survey const surveyMatch = originalSrc.match(/https:\/\/fortnite\.gg\/img\/items-survey\/(\d+)\.jpg(\?.+)?/); if (surveyMatch) { // Замена на изображение большего размера image.src = `https://fortnite.gg/img/items-survey/big/${surveyMatch[1]}.jpg${surveyMatch[2] || ''}`; return; } // Обработка иконок предметов const iconMatch = originalSrc.match(/\/img\/items\/(\d+)\/icon\.(png|jpg)(\?.+)?/); if (iconMatch) { const itemId = iconMatch[1]; const featuredUrl = `https://fortnite.gg/img/items/${itemId}/featured.png${iconMatch[3] || ''}`; // Проверка существования featured-изображения checkImage(featuredUrl, (exists) => { if (!exists) { // Если featured-изображения нет, пытаемся получить кадр из видео const videoUrl = `https://fnggcdn.com/items/${itemId}/video.mp4?t=${Date.now()}`; captureVideoFrame(videoUrl, (frameUrl) => { image.src = frameUrl || TRANSPARENT_PIXEL; // Fallback на прозрачный пиксель image.style.display = 'block'; if (!frameUrl) image.style.opacity = '0'; // Скрытие при неудаче }); return; } // Использование featured-изображения, если оно доступно image.onerror = null; image.src = featuredUrl; }); } }); } // Функция добавления панели управления на страницу function addControlPanel() { // Стили для панели управления const panelStyle = [ 'position: fixed', 'top: 20px', 'right: 20px', 'background: rgba(0,0,0,0.8)', 'padding: 15px', 'border-radius: 8px', 'z-index: 9999', 'box-shadow: 0 2px 10px rgba(0,0,0,0.5)' ].join(';'); // Стили для кнопок const buttonStyle = [ 'display: block', 'width: 100%', 'margin: 5px 0', 'padding: 10px', 'background: #5865F2', 'color: white', 'border: none', 'border-radius: 4px', 'cursor: pointer', 'font-family: inherit', 'transition: background 0.2s' ].join(';'); // Создание элементов панели управления const panel = document.createElement('div'); panel.style.cssText = panelStyle; // Кнопка замены изображений const replaceBtn = document.createElement('button'); replaceBtn.textContent = '🖼️ Replace Images'; replaceBtn.style.cssText = buttonStyle; replaceBtn.onclick = replaceImages; replaceBtn.onmouseover = () => replaceBtn.style.background = '#4752C4'; replaceBtn.onmouseout = () => replaceBtn.style.background = '#5865F2'; // Кнопка очистки кеша const clearBtn = document.createElement('button'); clearBtn.textContent = '🧹 Clear Cache'; clearBtn.style.cssText = buttonStyle; clearBtn.onclick = () => { if (confirm('Clear all cached data and reload?')) { localStorage.clear(); sessionStorage.clear(); window.location.reload(); } }; clearBtn.onmouseover = () => clearBtn.style.background = '#DA3636'; clearBtn.onmouseout = () => clearBtn.style.background = '#5865F2'; // Добавление кнопок на панель и панели на страницу panel.appendChild(replaceBtn); document.body.appendChild(panel); } // Добавление панели управления после полной загрузки страницы window.addEventListener('load', addControlPanel); })();