您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Save and restore video playback time using Firestore
当前为
// ==UserScript== // @name Video time tracker (Firestore) // @namespace http://tampermonkey.net/ // @version 1.0 // @description Save and restore video playback time using Firestore // @author Bui Quoc Dung // @match *://*/* // @grant GM_xmlhttpRequest // @run-at document-end // ==/UserScript== (function () { "use strict"; // 🔹 Firestore Configuration const FIRESTORE_URL = "PASTE YOUR FIRESTORE LINK"; const SAVE_INTERVAL = 10*1000; // seconds*1000 let video = null; let VIDEO_ID = ""; let lastSaveTime = 0; // 🔍 1. Generate Video ID function getVideoID() { const url = new URL(window.location.href); if (url.hostname.includes("youtube.com")) { return "youtube_" + url.searchParams.get("v"); } return window.location.pathname.replace(/[^a-zA-Z0-9]/g, ""); } // 🔍 2. Video Detection function findVideo() { video = document.querySelector("video") || detectPlyrVideo(); if (video) { console.log("🎥 Video element found"); initializeVideo(); } else { setTimeout(findVideo, 1000); console.log("🔍 Searching for video..."); } } // 🔍 3. Plyr.js Video Detection function detectPlyrVideo() { if (typeof Plyr !== "undefined" && Plyr.instances.length > 0) { return Plyr.instances[0].elements.container.querySelector("video"); } return null; } // ⬇️ 4. Load Saved Progress function loadSavedProgress() { GM_xmlhttpRequest({ method: "GET", url: `${FIRESTORE_URL}/${VIDEO_ID}`, onload: function (response) { try { const data = JSON.parse(response.responseText); if (data?.fields) { // Restore playback time if (data.fields.time?.integerValue) { video.currentTime = parseInt(data.fields.time.integerValue); console.log("⏩ Restored time:", video.currentTime); } // Display last saved date if (data.fields.date?.stringValue) { const savedDate = data.fields.date.stringValue; console.log("📅 Last saved:", savedDate); } } } catch (error) { console.error("⚠️ Error loading data:", error); } } }); } // ⬆️ 5. Save Playback Progress function savePlaybackProgress() { if (!video || video.paused || video.ended) return; const currentTime = Math.floor(video.currentTime); const currentDate = new Date().toISOString().split('T')[0]; // YYYY-MM-DD if (Date.now() - lastSaveTime >= SAVE_INTERVAL) { GM_xmlhttpRequest({ method: "PATCH", url: `${FIRESTORE_URL}/${VIDEO_ID}`, headers: { "Content-Type": "application/json" }, data: JSON.stringify({ fields: { time: { integerValue: currentTime }, date: { stringValue: currentDate } } }), onload: () => { lastSaveTime = Date.now(); console.log("💾 Saved:", currentTime, "| Date:", currentDate); } }); } } // 🔄 6. Handle Page Navigation (SPA) function monitorUrlChanges() { let previousUrl = location.href; setInterval(() => { if (location.href !== previousUrl) { previousUrl = location.href; VIDEO_ID = getVideoID(); console.log("🔄 Page changed - New video ID:", VIDEO_ID); findVideo(); } }, 1000); } // 🛠️ 7. Initialize Video Settings function initializeVideo() { loadSavedProgress(); video.addEventListener("timeupdate", savePlaybackProgress); video.addEventListener("seeked", savePlaybackProgress); } // 🚀 Start Script function init() { VIDEO_ID = getVideoID(); console.log("🔑 Video ID:", VIDEO_ID); findVideo(); monitorUrlChanges(); } init(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址