This commit is contained in:
lzyme.dev@gmail.com
2026-08-31 08:38:26 +08:00
parent ce59d82ed2
commit b7cfc8541c
2 changed files with 14886 additions and 15000 deletions
+92 -206
View File
@@ -1,7 +1,7 @@
// ==UserScript==
// @name JHS-enhance
// @namespace JHS-enhance
// @version 3.3.7
// @version 3.3.9
// @author xiebro,fireinrain
// @description Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers
// @license MIT
@@ -254,10 +254,9 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
}
})(),
isSearchPage = currentHref$1.includes("/search?q") || currentHref$1.includes("/search/") || currentHref$1.includes("/users/"),
Status_RUNNING = "RUNNING", Status_SUCCESS = "SUCCESS", Status_FAIL = "FAIL",
Status_LOADING = "LOADING", Status_FILTER$1 = "filter", Status_FAVORITE$1 = "favorite",
Status_HAS_DOWN$1 = "hasDown", Status_HAS_WATCH$1 = "hasWatch", NO = "no", YES$1 = "yes",
qualityOptions = [{
Status_RUNNING = "RUNNING", Status_SUCCESS = "SUCCESS", Status_FAIL = "FAIL", Status_LOADING = "LOADING",
Status_FILTER$1 = "filter", Status_FAVORITE$1 = "favorite", Status_HAS_DOWN$1 = "hasDown",
Status_HAS_WATCH$1 = "hasWatch", NO = "no", YES$1 = "yes", qualityOptions = [{
id: "video-mhb",
quality: "dmb_w",
text: "旧视频源-中画质宽版 (404p)",
@@ -1631,8 +1630,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
async batchRemoveCars(carNumList) {
if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数");
const carList = await this.getCarList(), initialLength = carList.length,
carNumsSet = new Set(carNumList),
const carList = await this.getCarList(), initialLength = carList.length, carNumsSet = new Set(carNumList),
updatedList = carList.filter(((car) => !carNumsSet.has(car.carNum))),
removedCount = initialLength - updatedList.length;
if (0 === removedCount) return removedCount;
@@ -1649,8 +1647,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
if (!starId) throw new Error("缺失starId");
if (!name2) throw new Error("缺失name");
if (!role) throw new Error("缺失role");
const blacklist = await this.getBlacklist(),
existData = blacklist.find(((item2) => item2.starId === starId));
const blacklist = await this.getBlacklist(), existData = blacklist.find(((item2) => item2.starId === starId));
if (existData) {
existData.url = url;
existData.role = role;
@@ -1699,8 +1696,8 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
async batchSaveBlacklistCarList(carDataList) {
const carList = await this.getCarList();
let blacklistCarList = await this.getBlacklistCarList(), hasChanged = false,
copyBlacklistCarList = null, carNumList = [];
let blacklistCarList = await this.getBlacklistCarList(), hasChanged = false, copyBlacklistCarList = null,
carNumList = [];
for (const carData of carDataList) {
let existBlacklistCarData = blacklistCarList.find(((item) => item.carNum === carData.carNum));
if (existBlacklistCarData) {
@@ -1751,15 +1748,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
const favoriteActressesInfoList = await this.getFavoriteActressList();
let resultCount = 0;
for (const actress of actressList) {
let {
starId,
name: name2,
allName,
avatar,
lastCheckTime,
lastPublishTime,
actressType
} = actress;
let {starId, name: name2, allName, avatar, lastCheckTime, lastPublishTime, actressType} = actress;
if (!starId) throw new Error("缺失starId");
if (!name2) throw new Error("缺失name");
allName || (allName = [name2]);
@@ -2198,8 +2187,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
$(document).on("keydown.globalLayerEsc", this._boundHandler);
}
-1 === this.layerIndexStack.indexOf(layerIndex) && this.layerIndexStack.push(layerIndex);
const $iframe = $(`#layui-layer-iframe${layerIndex}`),
eventNamespace = `keydown.layerEsc${layerIndex}`;
const $iframe = $(`#layui-layer-iframe${layerIndex}`), eventNamespace = `keydown.layerEsc${layerIndex}`;
try {
const iframeDocument = null == (_a2 = $iframe[0]) ? void 0 : _a2.contentDocument;
if (iframeDocument) {
@@ -2229,8 +2217,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
}
loopDetector(condition, after, detectInterval = 20, timeout = 1e4, runWhenTimeout = true) {
const uuid = Math.random(), start = (/* @__PURE__ */ new Date()).getTime(),
stopAndRun = (shouldRun) => {
const uuid = Math.random(), start = (/* @__PURE__ */ new Date()).getTime(), stopAndRun = (shouldRun) => {
clearInterval(this.intervalContainer[uuid]);
shouldRun && after && after();
delete this.intervalContainer[uuid];
@@ -2295,8 +2282,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim
now = dateString ? new Date(dateString) : /* @__PURE__ */ new Date();
const year = now.getFullYear(), month = String(now.getMonth() + 1).padStart(2, "0"),
day = String(now.getDate()).padStart(2, "0"), hours = String(now.getHours()).padStart(2, "0"),
minutes = String(now.getMinutes()).padStart(2, "0"),
seconds = String(now.getSeconds()).padStart(2, "0");
minutes = String(now.getMinutes()).padStart(2, "0"), seconds = String(now.getSeconds()).padStart(2, "0");
return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`;
}
@@ -2631,12 +2617,10 @@ ${value}\r
throw e;
}
if (!fileSize || fileSize <= 0) throw new Error("获取到的文件大小无效或服务器拒绝提供大小信息。");
const numChunks = Math.ceil(fileSize / 1048576), chunkPromises = [],
downloadedChunks = new Array(numChunks);
const numChunks = Math.ceil(fileSize / 1048576), chunkPromises = [], downloadedChunks = new Array(numChunks);
clog.log(`文件将被分为 ${numChunks} 块进行下载 (每块约 ${1.toFixed(2)} MB)`);
for (let i = 0; i < numChunks; i++) {
const start = 1048576 * i,
rangeHeader = `bytes=${start}-${Math.min(start + 1048576 - 1, fileSize - 1)}`,
const start = 1048576 * i, rangeHeader = `bytes=${start}-${Math.min(start + 1048576 - 1, fileSize - 1)}`,
chunkPromise = await utils.retry((() => new Promise(((resolve, reject) => {
const currentHeaders = {
...headers,
@@ -2873,8 +2857,7 @@ ${value}\r
$sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => {
nameList.push(name2.trim());
}));
let role = $(".section-meta:contains('男優')").length > 0 ? "actor" : "actress",
movieType = "censored";
let role = $(".section-meta:contains('男優')").length > 0 ? "actor" : "actress", movieType = "censored";
nameList.some(((n) => n.includes("無碼"))) && (movieType = "uncensored");
currentHref2.includes("uncensored") && (movieType = "uncensored");
let blacklistUrl = null, starId = null;
@@ -3448,11 +3431,7 @@ ${value}\r
if (isJavDb$1 && pageNum > maxPage || currentHref$1.includes("month")) {
const beyond60Plugin = this.getBean("Beyond60Plugin");
if (beyond60Plugin) {
const {
html: html2,
nextUrl,
hasMore
} = await beyond60Plugin.handleBeyond60(this.nextUrl);
const {html: html2, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(this.nextUrl);
if (html2) {
const pageTop2 = this.container.scrollHeight;
this.pageItems.push({
@@ -3536,8 +3515,7 @@ ${value}\r
updatePageUrl_old(href) {
window.history.pushState({}, "", href);
if (isJavBus$1) {
const match = href.match(/\/(page|star\/.*?)\/(\d+)/),
pageNumber = match ? parseInt(match[2], 10) : null;
const match = href.match(/\/(page|star\/.*?)\/(\d+)/), pageNumber = match ? parseInt(match[2], 10) : null;
document.title = document.title.replace(/第\d+頁/, "第" + pageNumber + "頁");
}
}
@@ -3656,8 +3634,7 @@ ${value}\r
type: "file",
check_name_mode: "auto_rename"
};
const headers = await this.getHeaders(),
createFileResult = await gmHttp.post(createFileUrl, data, headers),
const headers = await this.getHeaders(), createFileResult = await gmHttp.post(createFileUrl, data, headers),
upload_id = createFileResult.upload_id, upload_file_id = createFileResult.file_id,
upload_url = createFileResult.part_info_list[0].upload_url;
show.info("开始上传文件...");
@@ -4943,7 +4920,7 @@ ${value}\r
<div class="setting-item">
<span class="setting-label">
<span data-tip="匹配到不规则文件名时自动重命名为标准番号格式,如 mdvr00317-3.mp4 → MDVR-317-3.mp4">❓ </span>启用不规则重命名:
<span data-tip="匹配到不规则文件名时自动重命名为标准番号格式,如 mdvr00317-3.mp4 → MDVR-317-3.mp4">❓ </span>不规则重命名 <span style="font-size:11px;color:#999;">(详情页生效,有延迟)</span>:
</span>
<div class="form-content" style="text-align: right;">
<input type="checkbox" id="enable115AutoRename" class="mini-switch">
@@ -5072,13 +5049,11 @@ ${value}\r
$("#enableHandleSvg").prop("checked", !settingObj.enableHandleSvg || settingObj.enableHandleSvg === YES$1);
$("#enableSiteSvg").prop("checked", !settingObj.enableSiteSvg || settingObj.enableSiteSvg === YES$1);
$("#enableCopySvg").prop("checked", !settingObj.enableCopySvg || settingObj.enableCopySvg === YES$1);
const otherSitePlugin = this.getBean("OtherSitePlugin"),
missAvUrl = await otherSitePlugin.getMissAvUrl(),
const otherSitePlugin = this.getBean("OtherSitePlugin"), missAvUrl = await otherSitePlugin.getMissAvUrl(),
jableUrl = await otherSitePlugin.getjableUrl(),
javTrailersUrl = await otherSitePlugin.getJavTrailersUrl(),
av123Url = await otherSitePlugin.getAv123Url(), javDbUrl = await otherSitePlugin.getJavDbUrl(),
javBusUrl = await otherSitePlugin.getJavBusUrl(),
supJavUrl = await otherSitePlugin.getSupJavUrl();
javBusUrl = await otherSitePlugin.getJavBusUrl(), supJavUrl = await otherSitePlugin.getSupJavUrl();
$("#missAvUrl").val(missAvUrl);
$("#jableUrl").val(jableUrl);
$("#javTrailersUrl").val(javTrailersUrl);
@@ -5736,8 +5711,7 @@ ${value}\r
const reader = new FileReader();
reader.onload = (event) => {
try {
const content = event.target.result.toString(),
updateJsonData = JSON.parse(content);
const content = event.target.result.toString(), updateJsonData = JSON.parse(content);
layer.confirm("确定是否要覆盖导入?", {
icon: 3,
title: "确认覆盖",
@@ -5798,8 +5772,7 @@ ${value}\r
}
let loadObj = loading();
try {
const aliyunApi = new AliyunApi(refresh_token),
fileList = await aliyunApi.getBackupList(this.folderName);
const aliyunApi = new AliyunApi(refresh_token), fileList = await aliyunApi.getBackupList(this.folderName);
this.openFileListDialog(fileList, aliyunApi, "阿里云盘");
} catch (e) {
console.error(e);
@@ -6324,12 +6297,7 @@ ${value}\r
}
let carNumList = [], lastPublishTime = null;
for (const element of movieList) {
const $item = $(element), {
carNum: carNum2,
url,
title,
publishTime
} = this.getBoxCarInfo($item);
const $item = $(element), {carNum: carNum2, url, title, publishTime} = this.getBoxCarInfo($item);
if (!carNum2) continue;
if (!filterKeywordList.find(((kw) => title.includes(kw) || carNum2.startsWith(kw))) && !filterActorActressCarNumList.has(carNum2)) {
lastPublishTime || (lastPublishTime = publishTime);
@@ -6589,8 +6557,7 @@ ${value}\r
}]), totalCount = fullActressList.length, totalPages = Math.ceil(totalCount / this.pageSize),
startIndex = (this.currentPage - 1) * this.pageSize, endIndex = startIndex + this.pageSize,
pagedData = fullActressList.slice(startIndex, endIndex),
javDbUrl = await this.getBean("OtherSitePlugin").getJavDbUrl(),
taskPlugin = this.getBean("TaskPlugin"),
javDbUrl = await this.getBean("OtherSitePlugin").getJavDbUrl(), taskPlugin = this.getBean("TaskPlugin"),
checkNewVideo_ruleTime = await storageManager.getSetting("checkNewVideo_ruleTime") || 8760,
cardsHtml = pagedData.map(((data) => {
var _a2, _b, _c;
@@ -6699,8 +6666,7 @@ ${value}\r
}
async editActress(actress) {
const initialName = actress.name, initialAvatar = actress.avatar,
initialRemark = actress.remark || "",
const initialName = actress.name, initialAvatar = actress.avatar, initialRemark = actress.remark || "",
initialAllName = Array.isArray(actress.allName) ? actress.allName.join(",") : "",
initialNewVideoList = Array.isArray(actress.newVideoList) ? actress.newVideoList.join(",") : "",
starId = actress.starId,
@@ -6783,8 +6749,7 @@ ${value}\r
}));
$("#select-cdn-btn").on("click", (async () => {
await (async function () {
const initialIndex = currentCdnIndex,
radioOptions = CDN_SOURCES.map(((source, index2) => `
const initialIndex = currentCdnIndex, radioOptions = CDN_SOURCES.map(((source, index2) => `
<div style="margin-bottom: 10px;">
<input type="radio" id="cdn-${index2}" name="cdn-source" value="${index2}" ${index2 === initialIndex ? "checked" : ""} style="margin-right: 10px;">
<label for="cdn-${index2}">${source.name} ${source.json.includes("jsdelivr") ? "(推荐)" : ""}</label>
@@ -6830,8 +6795,7 @@ ${value}\r
utils.setupEscClose(index);
},
yes: async (index) => {
const newAvatar = $("#edit-actress-avatar").val().trim(),
newName = $("#edit-actress-name").val().trim(),
const newAvatar = $("#edit-actress-avatar").val().trim(), newName = $("#edit-actress-name").val().trim(),
newAllNameStr = $("#edit-actress-allname").val().trim(),
newVideoListStr = $("#edit-actress-newvideolist").val().trim(),
newRemark = $("#edit-remark").val().trim(), newActressType = $("#actressType").val();
@@ -6868,8 +6832,7 @@ ${value}\r
}
currentPage > 1 && totalPages > 5 && (paginationHtml += '<button class="pagination-btn" data-page="1" style="padding: 8px 12px; margin: 0 5px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">首页</button>');
currentPage > 1 && (paginationHtml += `<button class="pagination-btn" data-page="${currentPage - 1}" style="padding: 8px 12px; margin: 0 5px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">上一页</button>`);
let startPage = Math.max(1, currentPage - Math.floor(2.5)),
endPage = Math.min(totalPages, startPage + 5 - 1);
let startPage = Math.max(1, currentPage - Math.floor(2.5)), endPage = Math.min(totalPages, startPage + 5 - 1);
endPage - startPage < 4 && (startPage = Math.max(1, endPage - 5 + 1));
for (let i = startPage; i <= endPage; i++) {
paginationHtml += `<button class="pagination-btn page-number-btn ${i === currentPage ? "active" : ""}" data-page="${i}" style="padding: 8px 12px; margin: 0 3px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; ${i === currentPage ? "background: #007bff; color: white; border-color: #007bff;" : ""}">${i}</button>`;
@@ -6980,12 +6943,10 @@ ${value}\r
content: imageListHtml,
btn: ["关闭"],
success: (selectionLayero, selectionIndex) => {
const $container = $(selectionLayero),
$images = $container.find(".gfriends-selectable-img"),
const $container = $(selectionLayero), $images = $container.find(".gfriends-selectable-img"),
$prompt = $container.find("#gfriends-prompt");
$images.each((function () {
const $img = $(this), wrapperId = $img.data("wrapper-id"),
$wrapper = $container.find(`#${wrapperId}`),
const $img = $(this), wrapperId = $img.data("wrapper-id"), $wrapper = $container.find(`#${wrapperId}`),
$sizeTag = $container.find(`.gfriends-size-tag[data-size-for="${wrapperId}"]`);
$img.on("load", (function () {
const width = this.naturalWidth, height = this.naturalHeight;
@@ -7477,8 +7438,7 @@ ${value}\r
const initialCarNum = item.carNum, initialNames = item.names || "", initialUrl = item.url || "",
initialStatus = item.status, initialRemark = item.remark || "",
textareaStyle = "width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; min-height: 60px; overflow-y: hidden;",
inputStyle = "width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;",
editFormHtml = `
inputStyle = "width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;", editFormHtml = `
<div style="padding: 20px;">
<div style="margin-bottom: 15px;">
<label style="display: block; margin-bottom: 5px; font-weight: bold;">番号:</label>
@@ -7543,8 +7503,7 @@ ${value}\r
},
yes: async (index) => {
const newNames = $("#edit-names").val().trim(), newStatus = $("#edit-status").val(),
newUrl = $("#edit-url").val().trim(), newRemark = $("#edit-remark").val().trim(),
updatedRecord = {
newUrl = $("#edit-url").val().trim(), newRemark = $("#edit-remark").val().trim(), updatedRecord = {
...item,
names: newNames,
actionType: newStatus,
@@ -7632,8 +7591,7 @@ ${value}\r
clog.debug("解析其它画质预览视频", "设置-期望画质", settingDefaultVideoQuality);
const defaultVideoUrl = dmmVideoMap[selectDefaultQuality(Object.keys(dmmVideoMap), settingDefaultVideoQuality)];
clog.log("切换其它画质预览视频: ", defaultVideoUrl);
const $previewVideoEL = $("#preview-video"),
videoEl = $previewVideoEL.length ? $previewVideoEL[0] : null,
const $previewVideoEL = $("#preview-video"), videoEl = $previewVideoEL.length ? $previewVideoEL[0] : null,
isVideoElementHidden = !videoEl || utils.isHidden($previewVideoEL);
if ($previewVideoEL.length) {
if (videoEl) {
@@ -7834,9 +7792,8 @@ ${value}\r
}
static judgeHotkey(hotkeyString, event) {
const keyList = hotkeyString.toLowerCase().split("+").map(((k) => k.trim())),
ctrl = keyList.includes("ctrl"), shift = keyList.includes("shift"),
alt = keyList.includes("alt"),
const keyList = hotkeyString.toLowerCase().split("+").map(((k) => k.trim())), ctrl = keyList.includes("ctrl"),
shift = keyList.includes("shift"), alt = keyList.includes("alt"),
key = keyList.find(((k) => "ctrl" !== k && "shift" !== k && "alt" !== k));
return (this.isMac ? event.metaKey : event.ctrlKey) === ctrl && event.shiftKey === shift && event.altKey === alt && event.key.toLowerCase() === key;
}
@@ -7899,9 +7856,8 @@ ${value}\r
let videoEl = document.getElementById("vjs_video_3_html5_api");
videoEl && (videoEl.currentTime += 5);
}));
const urlParams = new URLSearchParams(window.location.search),
filterHotKey = urlParams.get("filterHotKey"), favoriteHotKey = urlParams.get("favoriteHotKey"),
speedVideoHotKey = urlParams.get("speedVideoHotKey");
const urlParams = new URLSearchParams(window.location.search), filterHotKey = urlParams.get("filterHotKey"),
favoriteHotKey = urlParams.get("favoriteHotKey"), speedVideoHotKey = urlParams.get("speedVideoHotKey");
filterHotKey && HotkeyManager.registerHotkey(filterHotKey, (() => window.parent.postMessage(filterHotKey, "*")));
favoriteHotKey && HotkeyManager.registerHotkey(favoriteHotKey, (() => window.parent.postMessage(favoriteHotKey, "*")));
speedVideoHotKey && HotkeyManager.registerHotkey(speedVideoHotKey, (() => {
@@ -8082,10 +8038,7 @@ ${value}\r
btn.textContent = "字幕搜索";
const refreshSubtitleFileTip = () => {
const groups = /* @__PURE__ */ new Map();
((getSubtitleEntries == null ? void 0 : getSubtitleEntries()) || []).forEach(({
directory,
files = []
}) => {
((getSubtitleEntries == null ? void 0 : getSubtitleEntries()) || []).forEach(({directory, files = []}) => {
const path = String(directory || "").trim();
if (!path) return;
if (!groups.has(path)) groups.set(path, /* @__PURE__ */ new Set());
@@ -8351,16 +8304,7 @@ ${value}\r
return score;
}
static renderTable({
container,
dataList,
previewBox,
statusNode,
overlay,
details,
getTargetCid,
kw = ""
}) {
static renderTable({container, dataList, previewBox, statusNode, overlay, details, getTargetCid, kw = ""}) {
const words = kw.split(/[-_.\s]+/).filter((word) => word.length > 1);
const highlightRegex = words.length ? new RegExp(`(${words.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})`, "gi") : null;
container.innerHTML = `
@@ -8821,10 +8765,7 @@ ${value}\r
static async filesSearchAll(search_value, params = {}) {
const res = await this.filesSearch(search_value, params);
const {count, page_size, data} = res;
return count > page_size && data.length ? this.filesSearch(search_value, {
...params,
limit: count
}) : res;
return count > page_size && data.length ? this.filesSearch(search_value, {...params, limit: count}) : res;
}
static filesSearchAllVideos(search_value, params = {}) {
@@ -9001,12 +8942,7 @@ ${value}\r
const files = [...videos, ...srts];
if (clean) await this.handleClean(files, file_id);
if (tags.length) this.handleTags(videos, tags);
if (rename) this.handleRename(files, file_id, {
rename,
renameTxt,
zh: zh || srts.length,
crack
});
if (rename) this.handleRename(files, file_id, {rename, renameTxt, zh: zh || srts.length, crack});
if (cover) {
try {
const {data} = await this.handleCover(cover, file_id, `${code}.cover.jpg`);
@@ -9049,8 +8985,7 @@ ${value}\r
if (currentHref$1.includes("collection_codes?movieId")) {
$("section").html("");
const urlParams = new URLSearchParams(window.location.search);
let movieId = urlParams.get("movieId"), carNum2 = urlParams.get("carNum"),
url = urlParams.get("url");
let movieId = urlParams.get("movieId"), carNum2 = urlParams.get("carNum"), url = urlParams.get("url");
movieId && carNum2 && url && this.openFc2Dialog(movieId, carNum2, url);
}
}
@@ -9084,8 +9019,7 @@ ${value}\r
}));
$("#filterBtn").on("click", ((event) => {
utils.q(event, `是否屏蔽${carNum2}?`, (async () => {
const actress = $("#data-actress").text(),
publishTime = $("#data-releaseDate").text();
const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text();
await storageManager.saveCar({
carNum: carNum2,
url: href,
@@ -9493,10 +9427,8 @@ ${value}\r
const rows = $("#magnet-table tr"), QUALITY_KEYWORDS = ["4k", "-c", "-u", "-uc"];
let hasHighQuality = false;
rows.each(((_, row) => {
const $row = $(row), $firstTd = $row.find("td:first-child"),
$firstLink = $firstTd.find("a:first-child"),
$secondLink = $firstTd.find("a:nth-child(2)"),
linkText = $firstLink.text().toLowerCase();
const $row = $(row), $firstTd = $row.find("td:first-child"), $firstLink = $firstTd.find("a:first-child"),
$secondLink = $firstTd.find("a:nth-child(2)"), linkText = $firstLink.text().toLowerCase();
linkText.includes("4k") && $firstLink.css("color", "#f40");
if (QUALITY_KEYWORDS.some(((keyword) => linkText.includes(keyword))) || $secondLink.length && $secondLink.text().includes("字幕")) {
hasHighQuality = true;
@@ -9918,8 +9850,7 @@ ${err.stack}` : "");
$('a[href*="rankings/top"]').on("click", ((event) => {
event.preventDefault();
event.stopPropagation();
const $target = $(event.target),
href = ($target.is("a") ? $target : $target.closest("a")).attr("href");
const $target = $(event.target), href = ($target.is("a") ? $target : $target.closest("a")).attr("href");
let queryString = href.includes("?") ? href.split("?")[1] : href;
const urlParams = new URLSearchParams(queryString);
this.checkLogin(event, urlParams);
@@ -10211,8 +10142,7 @@ ${err.stack}` : "");
}), 0);
}));
$("#search-btn").on("click", ((event) => {
let keyword = $("#search-keyword").val(),
searchCurrentType = $("#search-type option:selected").val();
let keyword = $("#search-keyword").val(), searchCurrentType = $("#search-type option:selected").val();
"" !== keyword && (window.location.href.includes("/search") ? window.location.href = "/search?q=" + keyword + "&f=" + searchCurrentType : window.open("/search?q=" + keyword + "&f=" + searchCurrentType));
}));
$("#search-img-btn").on("click", (() => {
@@ -10286,8 +10216,7 @@ ${err.stack}` : "");
if (headerSpan) {
const targetSpan = headerSpan.nextElementSibling;
if (targetSpan && "SPAN" === targetSpan.tagName) {
const identifierText = targetSpan.textContent.trim(),
copyButton = document.createElement("button");
const identifierText = targetSpan.textContent.trim(), copyButton = document.createElement("button");
copyButton.textContent = "复制";
copyButton.style.marginLeft = "10px";
copyButton.style.padding = "0 10px";
@@ -10608,10 +10537,7 @@ ${err.stack}` : "");
stats.loaded = data && data.byteLength ? data.byteLength : data && data.length ? data.length : stats.loaded || 0;
stats.total = stats.total || stats.loaded;
stats.bwEstimate = stats.loading.end > stats.loading.first ? Math.round(stats.total * 8e3 / (stats.loading.end - stats.loading.first)) : 0;
callbacks.onSuccess && callbacks.onSuccess({
data,
url: response.url
}, stats, context, response);
callbacks.onSuccess && callbacks.onSuccess({data, url: response.url}, stats, context, response);
},
onerror: () => {
callbacks.onError && callbacks.onError({
@@ -11126,13 +11052,11 @@ ${err.stack}` : "");
}
initEventListeners() {
const $uploadArea = $("#upload-area"), $fileInput = $("#image-file"),
$selectBtn = $("#select-image-btn"), $previewArea = $("#preview-area"),
$previewImage = $("#preview-image"), $actionBtns = $("#action-btns"),
const $uploadArea = $("#upload-area"), $fileInput = $("#image-file"), $selectBtn = $("#select-image-btn"),
$previewArea = $("#preview-area"), $previewImage = $("#preview-image"), $actionBtns = $("#action-btns"),
$searchImage = $("#handle-btn"), $cancelBtn = $("#cancel-btn"),
$urlInputContainer = $("#url-input-container"), $imageUrlInput = $("#image-url"),
$searchResults = $("#search-results"),
$siteBtnsContainer = $("#search-img-site-btns-container");
$searchResults = $("#search-results"), $siteBtnsContainer = $("#search-img-site-btns-container");
$uploadArea.on("dragover", ((e) => {
e.preventDefault();
$uploadArea.addClass("highlight");
@@ -11182,8 +11106,7 @@ ${err.stack}` : "");
$actionBtns.hide();
$searchResults.show();
$siteBtnsContainer.empty();
const key = "jhs_selectedSites",
selectedSites = JSON.parse(localStorage.getItem(key) || "{}");
const key = "jhs_selectedSites", selectedSites = JSON.parse(localStorage.getItem(key) || "{}");
this.siteList.forEach(((site) => {
const siteUrl = site.url.replace("{占位符}", encodeURIComponent(imgUrl)),
isChecked = false !== selectedSites[site.name];
@@ -11322,8 +11245,7 @@ ${err.stack}` : "");
}
async showRelated($eleBox, movieId) {
const enableLoadRelated = await storageManager.getSetting("enableLoadRelated", NO),
$magnets = $eleBox;
const enableLoadRelated = await storageManager.getSetting("enableLoadRelated", NO), $magnets = $eleBox;
if (movieId) {
$magnets.append(`
<div style="display: flex; align-items: center; margin: 16px 0; color: #666; font-size: 14px;">
@@ -11551,9 +11473,8 @@ ${err.stack}` : "");
createMagnetHub(keyword) {
keyword = keyword.replace("FC2-", "");
const $container = $('<div class="magnet-container"></div>'),
$tabs = $('<div class="magnet-tabs"></div>'), key = "jhs_magnetHub_selectedEngine",
savedEngineId = localStorage.getItem(key);
const $container = $('<div class="magnet-container"></div>'), $tabs = $('<div class="magnet-tabs"></div>'),
key = "jhs_magnetHub_selectedEngine", savedEngineId = localStorage.getItem(key);
let defaultEngineIndex = 0;
const $tabBox = $('<div style="display: flex;"></div>');
this.searchEngines.forEach(((engine, index) => {
@@ -11717,8 +11638,7 @@ ${err.stack}` : "");
const title = $el.find("td:nth-child(2) a").attr("title") || $el.find("td:nth-child(2) a").text().trim();
if (!title.toLowerCase().includes(keyword.toLowerCase())) return;
const magnet = $el.find("td:nth-child(3) a[href^='magnet:']").attr("href"),
size = $el.find("td:nth-child(4)").text().trim(),
date = $el.find("td:nth-child(5)").text().trim();
size = $el.find("td:nth-child(4)").text().trim(), date = $el.find("td:nth-child(5)").text().trim();
magnet && results.push({
title,
magnet,
@@ -11737,8 +11657,7 @@ ${err.stack}` : "");
const title = $el.find("td:nth-child(2) a").attr("title") || $el.find("td:nth-child(2) a").text().trim();
if (!title.toLowerCase().includes(keyword.toLowerCase())) return;
const magnet = $el.find("td:nth-child(3) a[href^='magnet:']").attr("href"),
size = $el.find("td:nth-child(4)").text().trim(),
date = $el.find("td:nth-child(5)").text().trim();
size = $el.find("td:nth-child(4)").text().trim(), date = $el.find("td:nth-child(5)").text().trim();
magnet && results.push({
title,
magnet,
@@ -12559,8 +12478,7 @@ ${err.stack}` : "");
await checkLoginRecursive();
}));
const handleCookie = () => {
const cookieStr = cookieInput.value,
expirySelect = document.getElementById("cookie-expiry-select");
const cookieStr = cookieInput.value, expirySelect = document.getElementById("cookie-expiry-select");
let maxAge = parseInt(expirySelect.value);
utils.addCookie(cookieStr, {
maxAge,
@@ -12843,8 +12761,7 @@ ${err.stack}` : "");
}
async retryMatch(buttonElement) {
const $el = $(buttonElement), $box2 = $el.closest(".movie-box, .item"),
carNum2 = $el.attr("data-keyword");
const $el = $(buttonElement), $box2 = $el.closest(".movie-box, .item"), carNum2 = $el.attr("data-keyword");
$el.replaceWith(`<a class='jhs-match-btn' title="匹配中...">匹配中...</a>`);
try {
const matchList = await this.searchFiles(carNum2);
@@ -13328,13 +13245,11 @@ ${err.stack}` : "");
$(document).on("confirm:complete", 'a[href*="/actors/"][href*="/uncollect"]', (async (event) => {
const [userConfirmed] = event.detail;
if (!userConfirmed) return;
const match = $(event.currentTarget).attr("href").match(listIdRegex),
actorId = match ? match[1] : null;
const match = $(event.currentTarget).attr("href").match(listIdRegex), actorId = match ? match[1] : null;
actorId && await this.removeActorFromStorage(actorId);
}));
$("#button-collect-actor").click((async (event) => {
const match = $("#button-collect-actor").attr("href").match(listIdRegex),
actorId = match ? match[1] : null;
const match = $("#button-collect-actor").attr("href").match(listIdRegex), actorId = match ? match[1] : null;
let nameList = [], $actor = $(".actor-section-name");
$actor.length && $actor.text().trim().split(",").forEach(((name2) => {
nameList.push(name2.trim());
@@ -13466,12 +13381,11 @@ ${err.stack}` : "");
showWaitDownBtn = await storageManager.getSetting("showWaitDownBtn", YES$1);
if (isJavDb$1) {
const isStarPage = currentHref$1.includes("/actors/");
let $el = $(".main-tabs, .tabs"), addBlacklistBtnText = "加入黑名单",
addBlacklistBtnColor = "#d22020", otherCss = "", blacklistItem = null;
let $el = $(".main-tabs, .tabs"), addBlacklistBtnText = "加入黑名单", addBlacklistBtnColor = "#d22020",
otherCss = "", blacklistItem = null;
if (isStarPage) {
$el = $(".toolbar, .section-addition").filter(":last");
const blacklist = await storageManager.getBlacklist(),
actressPageInfo = this.getActressPageInfo();
const blacklist = await storageManager.getBlacklist(), actressPageInfo = this.getActressPageInfo();
if (blacklist.find(((item) => item.starId === actressPageInfo.starId))) {
addBlacklistBtnText = "已加入黑名单";
addBlacklistBtnColor = "#885d5d";
@@ -13516,8 +13430,7 @@ ${err.stack}` : "");
const isStarPage = currentHref$1.includes("/star/");
let addBlacklistBtnText = "加入黑名单", addBlacklistBtnColor = "#d22020";
if (isStarPage) {
const blacklist = await storageManager.getBlacklist(),
actressPageInfo = this.getActressPageInfo();
const blacklist = await storageManager.getBlacklist(), actressPageInfo = this.getActressPageInfo();
if (blacklist.find(((item) => item.starId === actressPageInfo.starId))) {
addBlacklistBtnText = "已加入黑名单";
addBlacklistBtnColor = "#885d5d";
@@ -14008,8 +13921,8 @@ ${err.stack}` : "");
}
const baseUrl = await config.getBaseUrl(), searchUrl = config.searchPath(baseUrl, carNum2);
$btn.attr("href", searchUrl);
const html = await gmHttp.get(searchUrl, null, config.headers, true),
$dom = utils.htmlTo$dom(html), resultUrlList = [];
const html = await gmHttp.get(searchUrl, null, config.headers, true), $dom = utils.htmlTo$dom(html),
resultUrlList = [];
$dom.find(config.itemSelector).each(((index, element) => {
const $box2 = $(element);
if (!config.findCarNumOrTitle($box2).toLowerCase().includes(carNum2.toLowerCase())) return;
@@ -14115,8 +14028,7 @@ ${err.stack}` : "");
}
renderSettingsArea() {
const enabledSites = this.getEnabledSites(),
checkboxesDiv = document.getElementById("siteCheckboxes");
const enabledSites = this.getEnabledSites(), checkboxesDiv = document.getElementById("siteCheckboxes");
checkboxesDiv && (checkboxesDiv.innerHTML = this.siteConfigs.map(((config) => {
const isEnabled = enabledSites.includes(config.id);
return `
@@ -14661,8 +14573,7 @@ ${err.stack}` : "");
this.showImg($otherSvgElement, $otherImg, carNum2);
$otherSvgElement.html(this.videoSvg).attr("title", "播放视频");
}));
const $currentBox = $(event.target).closest(".item"),
$svgElement = $currentBox.find(".videoSvg");
const $currentBox = $(event.target).closest(".item"), $svgElement = $currentBox.find(".videoSvg");
if ("播放视频" === $svgElement.attr("title")) {
$svgElement.html(this.recoveryVideoSvg).attr("title", "切回封面");
const {carNum: carNum2} = this.getBoxCarInfo($currentBox);
@@ -14713,8 +14624,7 @@ ${err.stack}` : "");
$btn.hasClass("filterBtn") ? utils.q(event, `是否屏蔽${carNum2}?`, (() => handleAction(Status_FILTER$1))) : $btn.hasClass("favoriteBtn") ? handleAction(Status_FAVORITE$1).then() : $btn.hasClass("hasDownBtn") ? handleAction(Status_HAS_DOWN$1).then() : $btn.hasClass("hasWatchBtn") && handleAction(Status_HAS_WATCH$1).then();
$(".more-tools").stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide();
}));
const otherSitePlugin = this.getBean("OtherSitePlugin"),
missAvUrl = await otherSitePlugin.getMissAvUrl(),
const otherSitePlugin = this.getBean("OtherSitePlugin"), missAvUrl = await otherSitePlugin.getMissAvUrl(),
jableUrl = await otherSitePlugin.getjableUrl(), av123Url = await otherSitePlugin.getAv123Url();
$(document).on("click", ".site-jable, .site-miss-av, .site-123-av", ((event) => {
event.preventDefault();
@@ -14730,10 +14640,7 @@ ${err.stack}` : "");
$(document).on("click", ".titleSvg, .carNumSvg, .downSvg", ((event) => {
event.preventDefault();
event.stopPropagation();
const $box2 = $(event.currentTarget).closest(".item"), {
carNum: carNum2,
title
} = this.getBoxCarInfo($box2),
const $box2 = $(event.currentTarget).closest(".item"), {carNum: carNum2, title} = this.getBoxCarInfo($box2),
$img = $box2.find(isJavBus$1 ? ".photo-frame img" : ".cover img");
$(event.currentTarget).hasClass("titleSvg") ? utils.copyToClipboard("标题", title) : $(event.currentTarget).hasClass("carNumSvg") ? utils.copyToClipboard("番号", carNum2) : $(event.currentTarget).hasClass("downSvg") && fetch($img.attr("src")).then(((response) => response.blob())).then(((blob) => {
utils.download(blob, carNum2 + " " + title + ".jpg");
@@ -14959,8 +14866,7 @@ ${err.stack}` : "");
renderPagination() {
const $paginationList = $(".pagination-list");
$paginationList.empty();
let startPage = Math.max(1, this.currentPage - 2),
endPage = Math.min(this.maxPage, this.currentPage + 2);
let startPage = Math.max(1, this.currentPage - 2), endPage = Math.min(this.maxPage, this.currentPage + 2);
this.currentPage <= 3 ? endPage = Math.min(6, this.maxPage) : this.currentPage >= this.maxPage - 2 && (startPage = Math.max(this.maxPage - 5, 1));
if (startPage > 1) {
$paginationList.append('<li><a class="pagination-link" data-page="1">1</a></li>');
@@ -15106,8 +15012,7 @@ ${err.stack}` : "");
}));
$("#filterBtn").on("click", ((event) => {
utils.q(event, `是否屏蔽${carNum2}?`, (async () => {
const actress = $("#data-actress").text(),
publishTime = $("#data-publishTime").text();
const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text();
await storageManager.saveCar({
carNum: carNum2,
url: href,
@@ -15221,8 +15126,7 @@ ${err.stack}` : "");
async getActressInfo(fc2Num) {
let url = `https://fc2ppvdb.com/articles/${fc2Num.replace("FC2-", "")}`;
const html = await gmHttp.get(url), $dom = $(html),
actressNodeList = $dom.find("div").filter((function () {
const html = await gmHttp.get(url), $dom = $(html), actressNodeList = $dom.find("div").filter((function () {
return 0 === $(this).text().trim().indexOf("女優:");
}));
if (0 === actressNodeList.length || actressNodeList.length > 1) {
@@ -16046,8 +15950,7 @@ ${err.stack}` : "");
await this.clearKeywordBlacklist();
})).on("click", ".open-url", ((event) => {
event.preventDefault();
const $el = $(event.currentTarget), url = $el.attr("data-url"),
name2 = $el.attr("data-name");
const $el = $(event.currentTarget), url = $el.attr("data-url"), name2 = $el.attr("data-name");
utils.openPage(url, name2, true, event);
})).on("click", "#checkBlacklistBtn", ((event) => {
utils.q({
@@ -16086,10 +15989,9 @@ ${err.stack}` : "");
async getTableData() {
const taskPlugin = this.getBean("TaskPlugin"), blacklist = await storageManager.getBlacklist(),
blacklistCarList = await storageManager.getBlacklistCarList(),
searchValue = $("#searchValue").val(), statusType = $("#statusType").val(),
$dataType = $("#dataType"), dataType = $dataType.val(), urlType = $("#urlType").val(),
blacklistCount = blacklist.length;
blacklistCarList = await storageManager.getBlacklistCarList(), searchValue = $("#searchValue").val(),
statusType = $("#statusType").val(), $dataType = $("#dataType"), dataType = $dataType.val(),
urlType = $("#urlType").val(), blacklistCount = blacklist.length;
let actorCount = 0, actressCount = 0, noStarCount = 0;
const filteredBlacklist = blacklist.map(((item) => {
"actor" === item.role ? actorCount++ : "actress" === item.role ? actressCount++ : "虚拟演员" === item.role && noStarCount++;
@@ -16263,8 +16165,7 @@ ${err.stack}` : "");
const prefix = carItem.carNum.split("-")[0] + "-";
dataMap[prefix] = (dataMap[prefix] || 0) + 1;
return dataMap;
}), {}),
sortedPrefixList = Object.entries(prefixMap).map((([prefix, count]) => ({
}), {}), sortedPrefixList = Object.entries(prefixMap).map((([prefix, count]) => ({
prefix,
count
}))).sort(((a, b) => b.count - a.count));
@@ -16367,8 +16268,7 @@ ${err.stack}` : "");
const pageNum = utils.getUrlParam(nextPageLink, "page") || 0,
beyond60Plugin = this.getBean("Beyond60Plugin");
if (isJavDb$1 && beyond60Plugin && pageNum > 60) {
let {html, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(nextPageLink),
mergeHtml = `
let {html, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(nextPageLink), mergeHtml = `
<div class ='movie-list'>${html}</div>
${nextUrl ? `<a class="pagination-next" href="${nextUrl}"></a>` : ""}
`;
@@ -16407,12 +16307,7 @@ ${err.stack}` : "");
const filterKeywordList = await storageManager.getTitleFilterKeyword();
let carDataList = [], lastPublishTime = null;
for (const element of movieList) {
const $item = $(element), {
carNum: carNum2,
url,
publishTime,
title
} = this.getBoxCarInfo($item);
const $item = $(element), {carNum: carNum2, url, publishTime, title} = this.getBoxCarInfo($item);
lastPublishTime || (lastPublishTime = publishTime);
filterKeywordList.find(((kw) => title.includes(kw) || carNum2.startsWith(kw))) || url && carNum2 && carDataList.push({
carNum: carNum2,
@@ -16442,8 +16337,8 @@ ${err.stack}` : "");
}
const carList = await storageManager.getCarList(),
blacklistCarList = await storageManager.getBlacklistCarList(),
carNumSet = new Set(carList.map(((car) => car.carNum))),
keywords = Array.from(processedKeywordsSet), waitRemoveCarNumList = [], removableCarData = [];
carNumSet = new Set(carList.map(((car) => car.carNum))), keywords = Array.from(processedKeywordsSet),
waitRemoveCarNumList = [], removableCarData = [];
for (const car of blacklistCarList) {
const carNum2 = car.carNum;
let matched = false;
@@ -16728,8 +16623,7 @@ ${err.stack}` : "");
else {
if ("visibility" !== settings.movieShowType) throw new Error("movieShowType值有误:" + settings.movieShowType);
{
const $content = $box2.children(),
borderStyle = shouldHide ? "1px solid rgb(192 176 176)" : "none",
const $content = $box2.children(), borderStyle = shouldHide ? "1px solid rgb(192 176 176)" : "none",
visibilityValue = shouldHide ? "hidden" : "visible";
$box2.css("border", borderStyle);
$content.css("visibility", visibilityValue);
@@ -16838,10 +16732,7 @@ ${err.stack}` : "");
event.preventDefault();
event.stopPropagation();
if ($(event.target).closest("div.meta-buttons").length) return;
const $box2 = $(event.target).closest(".item"), {
carNum: carNum2,
aHref
} = this.getBoxCarInfo($box2);
const $box2 = $(event.target).closest(".item"), {carNum: carNum2, aHref} = this.getBoxCarInfo($box2);
let dialogOpenDetail = await storageManager.getSetting("dialogOpenDetail", YES$1);
if (carNum2.includes("FC2-")) {
let movieId = this.parseMovieId(aHref);
@@ -16859,10 +16750,7 @@ ${err.stack}` : "");
}));
$(selector.boxSelector).on("click", ".item .video-title", (async (event) => {
if ($(event.target).closest('[class^="jhs-match-"]').length) return;
const $box2 = $(event.currentTarget).closest(".item"), {
carNum: carNum2,
aHref
} = this.getBoxCarInfo($box2);
const $box2 = $(event.currentTarget).closest(".item"), {carNum: carNum2, aHref} = this.getBoxCarInfo($box2);
if (carNum2.includes("FC2-")) {
event.preventDefault();
let movieId = this.parseMovieId(aHref);
@@ -16876,8 +16764,7 @@ ${err.stack}` : "");
url,
publishTime
} = this.getBoxCarInfo($box2);
let $actor = isJavDb$1 ? $(".actor-section-name") : $(".avatar-box .photo-info .pb10"),
actorName = "";
let $actor = isJavDb$1 ? $(".actor-section-name") : $(".avatar-box .photo-info .pb10"), actorName = "";
$actor.length && (actorName = $actor.text().trim().split(",")[0].replace("(無碼)", ""));
utils.q(event, `是否屏蔽番号 ${carNum2}?`, (async () => {
setTimeout((async () => {
@@ -17005,8 +16892,8 @@ ${err.stack}` : "");
img.title = "";
}));
if (isJavBus$1) {
const THUMB_PATH_REGEX = /\/(imgs|pics)\/(thumb|thumbs)\//,
IMG_EXT_REGEX = /(\.jpg|\.jpeg|\.png)$/i, replaceWithHd = (img) => {
const THUMB_PATH_REGEX = /\/(imgs|pics)\/(thumb|thumbs)\//, IMG_EXT_REGEX = /(\.jpg|\.jpeg|\.png)$/i,
replaceWithHd = (img) => {
if (img.src && THUMB_PATH_REGEX.test(img.src) && "true" !== img.dataset.hdReplaced) {
img.src = img.src.replace(THUMB_PATH_REGEX, "/$1/cover/").replace(IMG_EXT_REGEX, "_b$1");
img.dataset.hdReplaced = "true";
@@ -17982,8 +17869,7 @@ ${err.stack}` : "");
"none" !== this.container.style.display && (this.window.classList.contains("collapsed") || setTimeout((() => {
this.content.innerHTML = "";
if (0 === this.logs.length) return;
const allowedTypes = filterMap[this.currentFilter] || [],
fragment = document.createDocumentFragment();
const allowedTypes = filterMap[this.currentFilter] || [], fragment = document.createDocumentFragment();
this.logs.forEach(((logEntry) => {
if (allowedTypes.includes(logEntry.type)) {
const entryEl = this._createLogElement(logEntry);
File diff suppressed because one or more lines are too long