您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Сохраняет позицию видео на griffiny.ru и восстанавливает с нужной секунды.
// ==UserScript== // @name Griffiny.ru Video Position Saver // @namespace http://tampermonkey.net/ // @version 1.0 // @description Сохраняет позицию видео на griffiny.ru и восстанавливает с нужной секунды. // @author KiberAndy + Ai // @license MIT // @match *://griffiny.ru/* // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = 'griffiny_vps_'; let lastSavedTime = 0; let saveIntervalId = null; let settings = { saveIntervalMS: 1000, minSaveDifference: 0.1 }; const positionCache = {}; let positionRestored = false; function getVideoId() { try { // Предположим, что видео на griffiny.ru уникально по ID, например, через URL или DOM. const pathname = window.location.pathname; return pathname.split('/').pop() || "default"; } catch (e) { console.error('Ошибка при определении ID видео:', e); return "default"; } } function savePosition(videoElement, videoId) { const currentTime = videoElement.currentTime; if (Math.abs(currentTime - lastSavedTime) < settings.minSaveDifference) return; try { localStorage.setItem(STORAGE_KEY + videoId, currentTime); positionCache[videoId] = currentTime; lastSavedTime = currentTime; console.log(`[Griffiny VPS] Сохранено время для ${videoId}: ${currentTime.toFixed(2)} сек.`); } catch (e) { console.error('[Griffiny VPS] Ошибка сохранения позиции:', e); } } function restorePosition(videoElement, videoId) { let savedTime; if (positionCache.hasOwnProperty(videoId)) { savedTime = positionCache[videoId]; console.log(`[Griffiny VPS] Из кэша для ${videoId}: ${savedTime.toFixed(2)} сек.`); } else { const saved = localStorage.getItem(STORAGE_KEY + videoId); if (saved) { savedTime = parseFloat(saved); console.log(`[Griffiny VPS] Из localStorage для ${videoId}: ${savedTime.toFixed(2)} сек.`); } } if (savedTime !== undefined && !isNaN(savedTime)) { const applyTime = () => { if (savedTime < videoElement.duration) { videoElement.currentTime = savedTime; // 👇 Принудительно ставим паузу и пускаем проигрывание снова (важно для возможных специфичных особенностей сайта) videoElement.pause(); setTimeout(() => { videoElement.play().catch(() => {}); }, 100); } }; if (videoElement.readyState >= 1) { applyTime(); } else { videoElement.addEventListener('loadedmetadata', applyTime, { once: true }); } } } GM_registerMenuCommand('Настройки сохранения', () => { const newInterval = prompt("Интервал сохранения (мс):", settings.saveIntervalMS); const newThreshold = prompt("Порог изменения времени (сек):", settings.minSaveDifference); let parsedInterval = parseInt(newInterval, 10); let parsedThreshold = parseFloat(newThreshold); if (!isNaN(parsedInterval) && parsedInterval > 0) { settings.saveIntervalMS = parsedInterval; } if (!isNaN(parsedThreshold) && parsedThreshold > 0) { settings.minSaveDifference = parsedThreshold; } console.log(`[Griffiny VPS] Новые настройки: ${settings.saveIntervalMS} мс / ${settings.minSaveDifference} сек`); const video = document.querySelector('video'); if (video && !video.paused) { clearInterval(saveIntervalId); saveIntervalId = setInterval(() => { savePosition(video, getVideoId()); }, settings.saveIntervalMS); } }); GM_registerMenuCommand('Очистить все позиции', () => { if (confirm('Удалить все сохраненные позиции?')) { Object.keys(localStorage) .filter(key => key.startsWith(STORAGE_KEY)) .forEach(key => localStorage.removeItem(key)); for (let key in positionCache) { delete positionCache[key]; } console.log('[Griffiny VPS] Все позиции очищены.'); } }); function setup() { const video = document.querySelector('video'); if (!video) { console.warn("[Griffiny VPS] Видео не найдено"); return; } const videoId = getVideoId(); if (!positionRestored) { restorePosition(video, videoId); positionRestored = true; } if (saveIntervalId) clearInterval(saveIntervalId); video.addEventListener('play', () => { if (saveIntervalId) return; saveIntervalId = setInterval(() => { savePosition(video, videoId); }, settings.saveIntervalMS); }); video.addEventListener('pause', () => { if (saveIntervalId) { clearInterval(saveIntervalId); saveIntervalId = null; } }); video.addEventListener('seeking', () => { savePosition(video, videoId); }); window.addEventListener('beforeunload', () => { savePosition(video, videoId); }); // 💾 Экстренное сохранение при закрытии/сворачивании вкладки document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') { savePosition(video, videoId); } }); window.addEventListener('pagehide', () => { savePosition(video, videoId); }); } function initObserver() { const observer = new MutationObserver((mutations, obs) => { if (document.querySelector('video')) { obs.disconnect(); setup(); } }); observer.observe(document.body, { childList: true, subtree: true }); } if (document.querySelector('video')) { setup(); } else { initObserver(); } window.addEventListener('griffiny-navigate-finish', () => { setTimeout(() => { lastSavedTime = 0; positionRestored = false; setup(); }, 1000); }); })();