您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
删除首页看过一定进度的视频,只会记录最大进度,仅对以新窗口打开的页面有效,ctrl+i可导入记录
// ==UserScript== // @name YouTube不重看 // @namespace 蒋晓楠 // @version 20240331 // @description 删除首页看过一定进度的视频,只会记录最大进度,仅对以新窗口打开的页面有效,ctrl+i可导入记录 // @author 蒋晓楠 // @license MIT // @match https://www.youtube.com/ // @match https://www.youtube.com/watch?v=* // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_registerMenuCommand // @grant GM_addElement // ==/UserScript== //清理视频记录延时,单位秒 const ClearVideoSavedPercentDelay = 30; //清理视频记录几率,0到100的整数 const ClearVideoSavedPercentRate = 2; //移除视频间隔,单位秒 const RemoveVideoInterval = 1; //以下不懂的不要修改 //修改配置 function SetConfig(Key, Value) { GM_setValue("Config:" + Key, Value); } //获取配置 function GetConfig(Key, Default) { return GM_getValue("Config:" + Key, Default); } //删除配置 function RemoveConfig(Key) { GM_deleteValue("Config:" + Key); } //获取当前时间 function GetNowTime() { return parseInt((new Date().getTime() / 86400000).toString()); } //获取视频记录进度 function GetVideoSavedPercent(Identifier) { let Video = GM_getValue("Data", {})[Identifier]; return Video === undefined ? 0 : Video.Percent; } //设置视频记录进度 function SetVideoSavedPercent(Identifier, Percent) { let AllVideos = GM_getValue("Data", {}); AllVideos[Identifier] = {Percent: Percent, Expire: GetNewExpire()}; GM_setValue("Data", AllVideos); } //清理视频记录进度 function ClearVideoSavedPercent() { let NowDay = GetNowTime(); let AllVideos = GM_getValue("Data", {}); for (const Key in AllVideos) { if (AllVideos[Key].Expire < NowDay) { delete AllVideos[Key]; } } console.log(AllVideos); GM_setValue("Data", AllVideos); console.log("已清理过期的播放记录"); } //获取新的过期时间 function GetNewExpire() { return GetNowTime() + GetConfig("Duration", 180); } //获取视频标识符 function GetVideoIdentifier(Url) { return Object.fromEntries((new URL(Url)).searchParams).v; } function InitHomePage() { let RemovePercent = GetConfig("RemovePercent", 90); setInterval(() => { document.querySelectorAll("ytd-rich-item-renderer:not(.JXNProcessed)").forEach((Item) => { Item.classList.add("JXNProcessed"); let Link = Item.__shady_native_querySelector("#video-title-link") if (Link !== null) { let Percent = GetVideoSavedPercent(GetVideoIdentifier(Link.href)); if (Percent >= RemovePercent) { console.log("删除[" + Item.__shady_native_querySelector("#video-title").__shady_native_textContent + "]进度" + Percent); //用隐藏代替删除,因为删除了还会重新在原位置出现 Item.style.display = "none"; } } }); }, RemoveVideoInterval * 1000); } function InitVideoPage() { let Identifier = GetVideoIdentifier(location.href); let OldPercent = GetVideoSavedPercent(Identifier); let VideoElement = document.querySelector(".video-stream.html5-main-video"); //等待直到视频元素正确加载 let CheckInterval = setInterval(function () { if (!isNaN(VideoElement.duration)) { clearInterval(CheckInterval); let Duration = VideoElement.duration; console.log("原进度", OldPercent, "总时间", Duration); VideoElement.ontimeupdate = () => { let NowPercent = parseInt((VideoElement.currentTime / Duration * 100).toFixed()); if (NowPercent > OldPercent) { console.log("新进度", NowPercent); SetVideoSavedPercent(Identifier, NowPercent); OldPercent = NowPercent; } } VideoElement.ended = () => { if (OldPercent !== 100) { SetVideoSavedPercent(Identifier, 100); } } } }, 1000); } function InitImport() { let ImportFile = GM_addElement("input", { type: "file", hidden: true, accept: "application/json" }); ImportFile.onchange = () => { if (ImportFile.files.length > 0) { let JsonList = ImportFile.files[0]; let Reader = new FileReader(); Reader.onload = (Result) => { try { GM_setValue("Data", JSON.parse(Result.target.result)); alert("导入完成"); } catch (e) { alert("读取的文件格式不正确"); } }; Reader.readAsText(JsonList); } }; window.onkeydown = (e) => { if (e.ctrlKey && e.key === "i") { if (confirm("导入记录将会覆盖当前数据,是否继续?")) { ImportFile.click(); } } }; } function ShowInfo() { setTimeout(() => { console.log("当前时间", GetNowTime()); console.log("所有记录", GM_getValue("Data", {})); }, 1000); } function Run() { GM_registerMenuCommand("设置移除百分比", () => { let Interval = prompt("达到这个的才会删除", GetConfig("RemovePercent", 90)); console.log(Interval) if (Interval !== null) { SetConfig("RemovePercent", parseInt(Interval)); } }); GM_registerMenuCommand("设置记录进度有效期", () => { let Duration = prompt("设置记录视频播放进度有效期,单位天,超过这个时间的记录会被删除", "180"); console.log(Duration) if (Duration !== null) { SetConfig("Duration", parseInt(Duration)); } }); GM_registerMenuCommand("导出记录", () => { let ExportJson = document.createElement("a"); ExportJson.download = "Youtube不重看.json"; ExportJson.href = URL.createObjectURL(new Blob([JSON.stringify(GM_getValue("Data", {}))])); ExportJson.click(); }); InitImport(); setTimeout(() => { if (1 + Math.round(Math.random() * 99) <= ClearVideoSavedPercentRate) { ClearVideoSavedPercent(); } }, ClearVideoSavedPercentDelay * 1000); ShowInfo(); location.pathname === "/watch" ? InitVideoPage() : InitHomePage(); } Run();