自动标记看过的影片
// ==UserScript==
// @name JavDB Watched Marker
// @version 1.1
// @namespace https://gist.github.com/sqzw-x
// @description 自动标记看过的影片
// @match https://javdb.com/*
// @grant GM_registerMenuCommand
// @grant GM_addElement
// @license MIT
// ==/UserScript==
"use strict";
const get_localStorage = (key) => JSON.parse(localStorage.getItem(key));
const set_localStorage = (key, value) =>
localStorage.setItem(key, JSON.stringify(value));
const URL_SET_KEY = "javdb-watched-url-set";
const NUM_SET_KEY = "javdb-watched-num-set";
let watchedURLSet = new Set(get_localStorage(URL_SET_KEY));
let watchedNumSet = new Set(get_localStorage(NUM_SET_KEY));
// 创建隐藏的文件输入框
const fileInput = GM_addElement(document.body, "input", {
type: "file",
accept: ".json",
style: "display: none",
});
fileInput.addEventListener("change", handleFileSelect);
// 注册油猴菜单
GM_registerMenuCommand("导入看过列表", () => fileInput.click());
GM_registerMenuCommand("手动添加看过", showManualInputDialog);
// 处理文件导入
function handleFileSelect(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const r = JSON.parse(e.target.result);
// r is an array of objects
// each object has a url property and a number property
// add each url to watchedURLSet and each num to watchedNumSet
r.forEach((item) => {
watchedURLSet.add(item.url);
watchedNumSet.add(item.number);
});
set_localStorage(URL_SET_KEY, Array.from(watchedURLSet));
set_localStorage(NUM_SET_KEY, Array.from(watchedNumSet));
} catch (error) {
console.error("解析文件失败:", error);
alert("无法解析文件,请确保是有效的JSON格式");
}
};
reader.readAsText(file);
}
// 显示手动输入对话框
function showManualInputDialog() {
// 创建对话框容器
const dialogContainer = document.createElement("div");
dialogContainer.style.position = "fixed";
dialogContainer.style.top = "0";
dialogContainer.style.left = "0";
dialogContainer.style.width = "100%";
dialogContainer.style.height = "100%";
dialogContainer.style.backgroundColor = "rgba(0, 0, 0, 0.7)";
dialogContainer.style.display = "flex";
dialogContainer.style.justifyContent = "center";
dialogContainer.style.alignItems = "center";
dialogContainer.style.zIndex = "10000";
// 创建对话框内容
const dialog = document.createElement("div");
dialog.style.backgroundColor = "white";
dialog.style.padding = "20px";
dialog.style.borderRadius = "5px";
dialog.style.width = "300px";
dialog.style.maxWidth = "90%";
dialog.innerHTML = `
<h3 style="margin-top: 0">添加已观看视频</h3>
<div style="margin-bottom: 10px;">
<label for="url-input">URL或ID:</label>
<input id="url-input" type="text" style="width: 100%; box-sizing: border-box;" placeholder="例如: abc123">
</div>
<div style="margin-bottom: 15px;">
<label for="number-input">番号:</label>
<input id="number-input" type="text" style="width: 100%; box-sizing: border-box;" placeholder="例如: ABC-123">
</div>
<div style="text-align: right;">
<button id="cancel-btn" style="margin-right: 10px; padding: 5px 10px;">取消</button>
<button id="save-btn" style="padding: 5px 10px;">保存</button>
</div>
`;
dialogContainer.appendChild(dialog);
document.body.appendChild(dialogContainer);
// 添加事件监听
document.getElementById("cancel-btn").addEventListener("click", () => {
document.body.removeChild(dialogContainer);
});
document.getElementById("save-btn").addEventListener("click", () => {
const urlInput = document.getElementById("url-input").value.trim();
const numberInput = document.getElementById("number-input").value.trim();
if (urlInput) {
// 从URL中提取ID部分
const urlId = urlInput.includes("/v/")
? urlInput.split("/v/")[1]
: urlInput;
watchedURLSet.add(urlId);
set_localStorage(URL_SET_KEY, Array.from(watchedURLSet));
}
if (numberInput) {
watchedNumSet.add(numberInput);
set_localStorage(NUM_SET_KEY, Array.from(watchedNumSet));
}
if (urlInput || numberInput) {
alert("已添加到观看列表");
markWatchedVideos(); // 重新标记视频
} else {
alert("请至少输入一项");
return;
}
document.body.removeChild(dialogContainer);
});
}
// 标记已看过的视频
function markWatchedVideos() {
const videos = document.querySelectorAll(".item");
const watched = (v) => {
const link = v.querySelector("a");
if (link) {
const url = link.getAttribute("href")?.replace("/v/", "");
return url && watchedURLSet.has(url) ? "看过" : null;
}
const num = v.querySelector(".video-title strong").textContent;
return num && watchedNumSet.has(num) ? "可能看过" : null;
};
videos.forEach((v) => {
const t = watched(v);
if (t) {
const marker = document.createElement("span");
marker.className = "review";
marker.textContent = t;
v.querySelector(".cover").appendChild(marker);
}
});
}
// 初始化
function init() {
markWatchedVideos();
}
init();