@@ -4969,6 +5001,8 @@ ${value}\r
})).on("keydown", ((event) => this.handleHotkeyInput(event, $element)));
}));
$("#enableImageHotKey").prop("checked", !!settingObj.enableImageHotKey && settingObj.enableImageHotKey === YES$1);
+ $("#enable115OfflineFormat").prop("checked", !!settingObj.enable115OfflineFormat && settingObj.enable115OfflineFormat === YES$1);
+ $("#offlineFolderFormat").val(settingObj.offlineFolderFormat || "");
}
handleHotkeyInput(event, $input) {
event.preventDefault();
@@ -5041,7 +5075,7 @@ ${value}\r
storageManager.saveSettingItem("containerWidth", containerWidth + 70);
}));
$("#dialogOpenDetail").on("change", ((event) => {
- let dialogOpenDetail = $("#dialogOpenDetail").is(":checked") ? YES$1 : NO;
+ let dialogOpenDetail = $("#dialogOpenDetail").is(":checked") ? YES$1 : NO$1;
storageManager.saveSettingItem("dialogOpenDetail", dialogOpenDetail);
}));
$("#showFilterItem").prop("checked", !!settingObj.showFilterItem && settingObj.showFilterItem === YES$1);
@@ -5051,32 +5085,32 @@ ${value}\r
$("#showHasDownItem").prop("checked", !settingObj.showHasDownItem || settingObj.showHasDownItem === YES$1);
$("#showHasWatchItem").prop("checked", !settingObj.showHasWatchItem || settingObj.showHasWatchItem === YES$1);
$("#showFilterItem").on("change", (async (event) => {
- let showFilterItem = $("#showFilterItem").is(":checked") ? YES$1 : NO;
+ let showFilterItem = $("#showFilterItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showFilterItem", showFilterItem);
window.refresh();
}));
$("#showFilterActorItem").on("change", (async (event) => {
- let showFilterActorItem = $("#showFilterActorItem").is(":checked") ? YES$1 : NO;
+ let showFilterActorItem = $("#showFilterActorItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showFilterActorItem", showFilterActorItem);
window.refresh();
}));
$("#showFilterKeywordItem").on("change", (async (event) => {
- let showFilterKeywordItem = $("#showFilterKeywordItem").is(":checked") ? YES$1 : NO;
+ let showFilterKeywordItem = $("#showFilterKeywordItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showFilterKeywordItem", showFilterKeywordItem);
window.refresh();
}));
$("#showFavoriteItem").on("change", (async (event) => {
- let showFavoriteItem = $("#showFavoriteItem").is(":checked") ? YES$1 : NO;
+ let showFavoriteItem = $("#showFavoriteItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showFavoriteItem", showFavoriteItem);
window.refresh();
}));
$("#showHasDownItem").on("change", (async (event) => {
- let showHasDownItem = $("#showHasDownItem").is(":checked") ? YES$1 : NO;
+ let showHasDownItem = $("#showHasDownItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showHasDownItem", showHasDownItem);
window.refresh();
}));
$("#showHasWatchItem").on("change", (async (event) => {
- let showHasWatchItem = $("#showHasWatchItem").is(":checked") ? YES$1 : NO;
+ let showHasWatchItem = $("#showHasWatchItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showHasWatchItem", showHasWatchItem);
window.refresh();
}));
@@ -5088,23 +5122,23 @@ ${value}\r
};
$("#showAllItem").prop("checked", !!settingObj.showAllItem && settingObj.showAllItem === YES$1);
$("#showAllItem").on("change", (async (event) => {
- let showAllItem = $("#showAllItem").is(":checked") ? YES$1 : NO;
+ let showAllItem = $("#showAllItem").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("showAllItem", showAllItem);
updateOtherCheckboxesState();
window.refresh();
}));
updateOtherCheckboxesState();
$("#needClosePage").on("change", (async (event) => {
- await storageManager.saveSettingItem("needClosePage", $("#needClosePage").is(":checked") ? YES$1 : NO);
+ await storageManager.saveSettingItem("needClosePage", $("#needClosePage").is(":checked") ? YES$1 : NO$1);
window.refresh();
}));
$("#autoPage").on("change", (async (event) => {
- const autoPage = $("#autoPage").is(":checked") ? YES$1 : NO;
+ const autoPage = $("#autoPage").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("autoPage", autoPage);
autoPage === YES$1 ? ($("#sort-toggle-btn").hide(), $("#one-time-sort-btn").show()) : ($("#sort-toggle-btn").show(), $("#one-time-sort-btn").hide());
}));
$("#translateTitle").on("change", (async (event) => {
- const translateTitle = $("#translateTitle").is(":checked") ? YES$1 : NO;
+ const translateTitle = $("#translateTitle").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("translateTitle", translateTitle);
if (translateTitle === YES$1) {
await this.getBean("ListPagePlugin").doFilter();
@@ -5116,38 +5150,38 @@ ${value}\r
}));
$("#hoverBigImg").prop("checked", !!settingObj.hoverBigImg && settingObj.hoverBigImg === YES$1);
$("#hoverBigImg").on("change", (async (event) => {
- const hoverBigImg = $("#hoverBigImg").is(":checked") ? YES$1 : NO;
+ const hoverBigImg = $("#hoverBigImg").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("hoverBigImg", hoverBigImg);
hoverBigImg === YES$1 ? window.imageHoverPreviewObj = new ImageHoverPreview({
selector: this.getSelector().coverImgSelector
}) : window.imageHoverPreviewObj && window.imageHoverPreviewObj.destroy();
}));
$("#enableLoadActressInfo").on("change", (async (event) => {
- const enableLoadActressInfo = $("#enableLoadActressInfo").is(":checked") ? YES$1 : NO;
+ const enableLoadActressInfo = $("#enableLoadActressInfo").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enableLoadActressInfo", enableLoadActressInfo);
enableLoadActressInfo === YES$1 ? this.getBean("ActressInfoPlugin").loadActressInfo() : $(".actress-info").remove();
}));
$("#enableLoadOtherSite").on("change", (async (event) => {
- const enableLoadOtherSite = $("#enableLoadOtherSite").is(":checked") ? YES$1 : NO;
+ const enableLoadOtherSite = $("#enableLoadOtherSite").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enableLoadOtherSite", enableLoadOtherSite);
enableLoadOtherSite === YES$1 ? this.getBean("OtherSitePlugin").loadOtherSite().then() : $("#otherSiteBox").remove();
}));
$("#enableLoadScreenShot").prop("checked", !settingObj.enableLoadScreenShot || settingObj.enableLoadScreenShot === YES$1);
$("#enableLoadScreenShot").on("change", (async (event) => {
- const enableLoadScreenShot = $("#enableLoadScreenShot").is(":checked") ? YES$1 : NO;
+ const enableLoadScreenShot = $("#enableLoadScreenShot").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enableLoadScreenShot", enableLoadScreenShot);
enableLoadScreenShot === YES$1 ? this.getBean("ScreenShotPlugin").loadScreenShot().then() : $(".screen-container").remove();
}));
$("#enableLoadPreviewVideo").prop("checked", !settingObj.enableLoadPreviewVideo || settingObj.enableLoadPreviewVideo === YES$1);
$("#enableLoadPreviewVideo").on("change", (async (event) => {
- const enableLoadPreviewVideo = $("#enableLoadPreviewVideo").is(":checked") ? YES$1 : NO;
+ const enableLoadPreviewVideo = $("#enableLoadPreviewVideo").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enableLoadPreviewVideo", enableLoadPreviewVideo);
}));
$("#enable115AutoRename").prop("checked", !!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1);
$("#autoRenameScope").val(settingObj.autoRenameScope || "vr_only");
$("#autoRenameScopeRow").toggle(!!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1);
$("#enable115AutoRename").on("change", (async (event) => {
- const enable115AutoRename = $("#enable115AutoRename").is(":checked") ? YES$1 : NO;
+ const enable115AutoRename = $("#enable115AutoRename").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enable115AutoRename", enable115AutoRename);
$("#autoRenameScopeRow").toggle(enable115AutoRename === YES$1);
}));
@@ -5156,14 +5190,14 @@ ${value}\r
}));
$("#enable115Match").prop("checked", !!settingObj.enable115Match && settingObj.enable115Match === YES$1);
$("#enable115Match").on("change", (async (event) => {
- const enable115Match = $("#enable115Match").is(":checked") ? YES$1 : NO;
+ const enable115Match = $("#enable115Match").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enable115Match", enable115Match);
let movieList = $(this.getSelector().itemSelector).toArray();
await this.getBean("WangPan115MatchPlugin").matchMovieList(movieList);
}));
$("#enableVerticalModel").prop("checked", !!settingObj.enableVerticalModel && settingObj.enableVerticalModel === YES$1);
$("#enableVerticalModel").on("change", (async (event) => {
- const enableVerticalModel = $("#enableVerticalModel").is(":checked") ? YES$1 : NO;
+ const enableVerticalModel = $("#enableVerticalModel").is(":checked") ? YES$1 : NO$1;
await storageManager.saveSettingItem("enableVerticalModel", enableVerticalModel);
this.applyImageMode();
}));
@@ -5272,7 +5306,7 @@ ${value}\r
}
async applyImageMode() {
$("#verticalImgStyle").remove();
- if (await storageManager.getSetting("enableVerticalModel", NO) === YES$1) {
+ if (await storageManager.getSetting("enableVerticalModel", NO$1) === YES$1) {
let imgPosition = "100% 50% !important";
window.location.href.includes("/advanced_search?type=100") && (imgPosition = "50% 50% !important");
const verticalStyle = `
@@ -5443,11 +5477,11 @@ ${value}\r
settingObj.refresh_token = $("#refresh_token").val();
settingObj.highlightedTagNumber = $("#highlightedTagNumber").val();
settingObj.highlightedTagColor = $("#highlightedTagColor").val();
- settingObj.showWaitCheckBtn = $("#showWaitCheckBtn").is(":checked") ? YES$1 : NO;
+ settingObj.showWaitCheckBtn = $("#showWaitCheckBtn").is(":checked") ? YES$1 : NO$1;
settingObj.showWaitCheckBtn === YES$1 ? $("#waitCheckBtn").show() : $("#waitCheckBtn").hide();
- settingObj.showWaitDownBtn = $("#showWaitDownBtn").is(":checked") ? YES$1 : NO;
+ settingObj.showWaitDownBtn = $("#showWaitDownBtn").is(":checked") ? YES$1 : NO$1;
settingObj.showWaitDownBtn === YES$1 ? $("#waitDownBtn").show() : $("#waitDownBtn").hide();
- settingObj.randomOpenWaitDown = $("#randomOpenWaitDown").is(":checked") ? YES$1 : NO;
+ settingObj.randomOpenWaitDown = $("#randomOpenWaitDown").is(":checked") ? YES$1 : NO$1;
settingObj.checkConcurrencyCount = $("#checkConcurrencyCount").val();
settingObj.checkRequestSleep = $("#checkRequestSleep").val();
settingObj.enableCheckBlacklist = $("#enableCheckBlacklist").val();
@@ -5473,18 +5507,20 @@ ${value}\r
settingObj.javDbUrl = $("#javDbUrl").val().replace(/\/$/, "");
settingObj.javBusUrl = $("#javBusUrl").val().replace(/\/$/, "");
settingObj.supJavUrl = $("#supJavUrl").val().replace(/\/$/, "");
- settingObj.enableTitleSelectFilter = $("#enableTitleSelectFilter").is(":checked") ? YES$1 : NO;
- settingObj.enableFavoriteActresses = $("#enableFavoriteActresses").is(":checked") ? YES$1 : NO;
- settingObj.enableSaveActressCarInfo = $("#enableSaveActressCarInfo").is(":checked") ? YES$1 : NO;
- settingObj.enableScreenSvg = $("#enableScreenSvg").is(":checked") ? YES$1 : NO;
- settingObj.enableVideoSvg = $("#enableVideoSvg").is(":checked") ? YES$1 : NO;
- settingObj.enableHandleSvg = $("#enableHandleSvg").is(":checked") ? YES$1 : NO;
- settingObj.enableSiteSvg = $("#enableSiteSvg").is(":checked") ? YES$1 : NO;
- settingObj.enableCopySvg = $("#enableCopySvg").is(":checked") ? YES$1 : NO;
+ settingObj.enableTitleSelectFilter = $("#enableTitleSelectFilter").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableFavoriteActresses = $("#enableFavoriteActresses").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableSaveActressCarInfo = $("#enableSaveActressCarInfo").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableScreenSvg = $("#enableScreenSvg").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableVideoSvg = $("#enableVideoSvg").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableHandleSvg = $("#enableHandleSvg").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableSiteSvg = $("#enableSiteSvg").is(":checked") ? YES$1 : NO$1;
+ settingObj.enableCopySvg = $("#enableCopySvg").is(":checked") ? YES$1 : NO$1;
$("#hotkey-panel [id]").map(((i, el) => el.id)).get().forEach(((containerId) => {
settingObj[containerId] = $(`#${containerId}`).val();
}));
- settingObj.enableImageHotKey = $("#enableImageHotKey").is(":checked") ? YES$1 : NO;
+ settingObj.enableImageHotKey = $("#enableImageHotKey").is(":checked") ? YES$1 : NO$1;
+ settingObj.enable115OfflineFormat = $("#enable115OfflineFormat").is(":checked") ? YES$1 : NO$1;
+ settingObj.offlineFolderFormat = $("#offlineFolderFormat").val();
await storageManager.saveSetting(settingObj);
let reviewKeywordList = [];
$("#reviewKeywordContainer .keyword-label").toArray().forEach(((item) => {
@@ -7439,7 +7475,7 @@ ${value}\r
}
}
async handleVideo() {
- if (await storageManager.getSetting("enableLoadPreviewVideo", YES$1) === NO) return;
+ if (await storageManager.getSetting("enableLoadPreviewVideo", YES$1) === NO$1) return;
const $videoEl = $("#preview-video");
if (!$videoEl.length) return;
const $videoContainer = $videoEl.parent();
@@ -9282,7 +9318,7 @@ ${value}\r
$foldCategoryBtn.on("click", (async (event) => {
event.preventDefault();
isFolded = !isFolded;
- localStorage.setItem("jhs_foldCategory", isFolded ? YES$1 : NO);
+ localStorage.setItem("jhs_foldCategory", isFolded ? YES$1 : NO$1);
const [newText2, newIcon2] = isFolded ? ["展开", "icon-angle-double-down"] : ["折叠", "icon-angle-double-up"];
$foldCategoryBtn.find("span").text(newText2).end().find("i").attr("class", newIcon2);
$subTags[isFolded ? "hide" : "show"]();
@@ -10779,7 +10815,7 @@ ${err.stack}` : "");
return "RelatedPlugin";
}
async showRelated($eleBox, movieId) {
- const enableLoadRelated = await storageManager.getSetting("enableLoadRelated", NO), $magnets = $eleBox;
+ const enableLoadRelated = await storageManager.getSetting("enableLoadRelated", NO$1), $magnets = $eleBox;
if (movieId) {
$magnets.append(`
@@ -10810,7 +10846,7 @@ ${err.stack}` : "");
} else {
$("#relatedContainer").hide();
$("#relatedFooter").hide();
- storageManager.saveSettingItem("enableLoadRelated", NO);
+ storageManager.saveSettingItem("enableLoadRelated", NO$1);
}
}));
$magnets.append('
');
@@ -12578,7 +12614,103 @@ ${err.stack}` : "");
$headerRow.append($("
").text("操作"));
}
}
+
+ static sanitizeDirName(str) {
+ if (!str) return "";
+ return str.replace(/[\\/:*?"<>|]/g, "").replace(/\s+/g, " ").trim();
+ }
+
+ static parseOfflineDirTemplate(str, params) {
+ if (!str || !params) return str;
+ return str.replace(/\$\{(\w+)\}/g, (match, key) => {
+ if (!params.hasOwnProperty(key)) return match;
+ const value = params[key] || "";
+ return WangPan115TaskPlugin.sanitizeDirName(String(value));
+ });
+ }
+
+ static async ensureDir(dirName, pid = 0) {
+ const result = await gmHttp.postFileFormData("https://webapi.115.com/files/add", {
+ pid,
+ cname: dirName
+ });
+ if (result && result.file_id) return result.file_id;
+ const searchRes = await searchFiles(dirName, 0, 1, {fc: 1});
+ if (searchRes && searchRes.data && searchRes.data.length > 0) {
+ const match = searchRes.data.find((d) => d.pid === pid || d.pid === String(pid));
+ if (match) return match.fid || match.file_id;
+ }
+ return null;
+ }
+
+ static async registerDirAsDownPath(fileId, dirName) {
+ await gmHttp.postFileFormData("https://webapi.115.com/offine/downpath", {
+ file_id: fileId
+ });
+ const list = await getDownPathList();
+ const created = list ? list.find((d) => d.file_id === fileId || String(d.file_id) === String(fileId)) : null;
+ return created ? created.id : null;
+ }
+
+ static async createMultiLevelDownPath(templatePath) {
+ const segments = templatePath.split("/").filter((s) => s.trim());
+ if (segments.length === 0) return null;
+ let pid = 0;
+ let fileId = null;
+ for (const seg of segments) {
+ fileId = await WangPan115TaskPlugin.ensureDir(seg.trim(), pid);
+ if (!fileId) {
+ console.error("[115离线] 创建目录失败:", seg);
+ return null;
+ }
+ pid = fileId;
+ }
+ const lastDirName = segments[segments.length - 1].trim();
+ const downPathId = await WangPan115TaskPlugin.registerDirAsDownPath(fileId, lastDirName);
+ console.log("[115离线] 多级目录创建完成:", templatePath, "→ downPathId=" + downPathId);
+ return downPathId;
+ }
+
+ getPageInfoForOffline() {
+ const baseInfo = this.getPageInfo();
+ const carNum2 = baseInfo.carNum || "";
+ let title = "", maker = "", actor = "";
+ if (isJavBus$1) {
+ title = $("h3").first().text().trim();
+ maker = $('span.header:contains("製作商:")').parent("p").text().replace("製作商:", "").trim() || $('span.header:contains("制作商:")').parent("p").text().replace("制作商:", "").trim();
+ const actorEl = $('span.genre a[href*="/star/"]').first();
+ actor = actorEl.length ? actorEl.text().trim() : "";
+ } else {
+ title = $(".current-title").first().text().trim() || $("h2.title.is-4 .current-title").first().text().trim() || $(".movie-title").first().text().trim();
+ maker = $('strong:contains("片商:")').parent().find(".value").text().trim() || $('strong:contains("片商:")').parent().find(".value").text().trim();
+ actor = $(".actor-female").first().text().trim() || $('strong:contains("演員:"), strong:contains("演员:")').parent().find(".value a").first().text().trim() || "";
+ }
+ const now = /* @__PURE__ */ new Date();
+ if (carNum2 && title) {
+ const upperTitle = title.toUpperCase();
+ const upperCode = carNum2.toUpperCase();
+ if (upperTitle.startsWith(upperCode)) {
+ title = title.substring(carNum2.length).replace(/^[\s\-_]+/, "").trim();
+ }
+ }
+ console.log("[115离线] 页面信息提取:", {code: carNum2, title, maker, actor});
+ return {
+ code: carNum2,
+ title,
+ maker,
+ actor,
+ date: utils.formatDate(now).split(" ")[0]
+ };
+ }
async getSavePathId(nyName) {
+ const enableCustom = await storageManager.getSetting("enable115OfflineFormat", NO);
+ if (enableCustom === YES) {
+ const template = await storageManager.getSetting("offlineFolderFormat", "");
+ if (template && template.includes("${")) {
+ const pageInfo = this.getPageInfoForOffline();
+ return WangPan115TaskPlugin.parseOfflineDirTemplate(template, pageInfo);
+ }
+ }
let savePath115 = await storageManager.getSetting("savePath115", "云下载");
nyName && (savePath115 = savePath115.replaceAll("{ny}", nyName));
savePath115 = savePath115.replaceAll("{date}", utils.formatDate(/* @__PURE__ */ new Date()));
@@ -12599,17 +12731,42 @@ ${err.stack}` : "");
});
return;
}
- const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId(),
- result = await (async (magnet, wp_path_id = "", uid, sign2, time2) => {
- const data = {
- url: encodeURIComponent(magnet),
- wp_path_id,
- uid,
- sign: sign2,
- time: time2
- };
- return await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=add_task_url", data);
- })(magnetLink, savePath || "", userId, sign, time);
+ const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId();
+ let wp_path_id = savePath || "";
+ if (!wp_path_id) {
+ const fullPath = await this.getSavePathId();
+ console.log("[115离线] 目录模板解析结果:", fullPath);
+ if (fullPath) {
+ if (fullPath.includes("/")) {
+ console.log("[115离线] 检测到多级目录,逐级创建:", fullPath);
+ const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
+ if (newId) wp_path_id = newId;
+ } else {
+ const downPathList = await getDownPathList();
+ if (downPathList && downPathList.length > 0) {
+ const matched = downPathList.find(((d) => d.name === fullPath));
+ if (matched) {
+ wp_path_id = matched.id;
+ console.log('[115离线] 目录匹配结果: 匹配到 "' + matched.name + '" -> id=' + matched.id);
+ } else {
+ console.log('[115离线] 目录匹配结果: 未匹配到 "' + fullPath + '",自动创建并注册');
+ const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
+ if (newId) wp_path_id = newId;
+ }
+ }
+ }
+ }
+ }
+ const result = await (async (magnet, wp_path_id2 = "", uid, sign2, time2) => {
+ const data = {
+ url: encodeURIComponent(magnet),
+ wp_path_id: wp_path_id2,
+ uid,
+ sign: sign2,
+ time: time2
+ };
+ return await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=add_task_url", data);
+ })(magnetLink, wp_path_id, userId, sign, time);
console.log("离线下载返回值:", result);
let infoHash = result.info_hash, fileId = await this.getFileId(userId, sign, time, infoHash),
openUrl = "https://115.com/?tab=offline&mode=wangpan";
@@ -13026,7 +13183,7 @@ ${err.stack}` : "");
}
async matchDetailPage(matchList) {
if (!window.isDetailPage) return;
- if (await storageManager.getSetting("enable115Match", NO) === NO) return;
+ if (await storageManager.getSetting("enable115Match", NO$1) === NO$1) return;
const $detail = $('\n \n \n \n \n | 115匹配 | \n \n \n | 名称 | \n 大小 | \n 时间 | \n 播放 | \n \n \n \n \n \n \n '),
$tbody = $detail.find("tbody");
try {
@@ -13083,7 +13240,7 @@ ${err.stack}` : "");
else $("#mag-submit-show").before($detail);
}
async matchMovieList(movieListElement) {
- if (await storageManager.getSetting("enable115Match", NO) !== NO) {
+ if (await storageManager.getSetting("enable115Match", NO$1) !== NO$1) {
await this.checkLoginStatus();
await this.processMovieElements(movieListElement);
} else $(".video-title [class^='jhs-match-']").remove();
@@ -13468,7 +13625,7 @@ ${err.stack}` : "");
}
async autoRenameFiles(carNum2, matchList) {
try {
- const enableAutoRename = await storageManager.getSetting("enable115AutoRename", NO);
+ const enableAutoRename = await storageManager.getSetting("enable115AutoRename", NO$1);
if (enableAutoRename !== YES) return;
const scope = await storageManager.getSetting("autoRenameScope", "vr_only");
if (scope === "vr_only" && !carNum2.toUpperCase().includes("VR")) return;
@@ -13710,7 +13867,7 @@ ${err.stack}` : "");
return itemList;
}
async logImageHeightsByRow() {
- if (await storageManager.getSetting("enableVerticalModel", NO) === YES$1) return;
+ if (await storageManager.getSetting("enableVerticalModel", NO$1) === YES$1) return;
const itemSelector = this.getSelector().itemSelector,
containerColumns = await storageManager.getSetting("containerColumns", 5),
itemList = await this.getVisibleImageItems(itemSelector, "img");
@@ -13781,8 +13938,8 @@ ${err.stack}` : "");
sortText = "当前排序方式: " + ("rateCount" === jhs_sortMethod ? "评价人数" : "date" === jhs_sortMethod ? "时间" : "默认");
$el.append(`
- 打开待鉴定
- 打开已收藏
+ 打开待鉴定
+ 打开已收藏
${isStarPage ? `
${addBlacklistBtnText}
一键屏蔽所有作品
@@ -13811,8 +13968,8 @@ ${err.stack}` : "");
}
$(".masonry").parent().prepend(`
- 打开待鉴定
- 打开已收藏
+ 打开待鉴定
+ 打开已收藏
${isStarPage ? `
${addBlacklistBtnText}
@@ -14019,7 +14176,7 @@ ${err.stack}` : "");
}
async openFavorite() {
let favoriteList, openCount = await storageManager.getSetting("waitCheckCount", 5),
- randomOpenWaitDown = await storageManager.getSetting("randomOpenWaitDown", NO),
+ randomOpenWaitDown = await storageManager.getSetting("randomOpenWaitDown", NO$1),
dataList = await storageManager.getCarList();
favoriteList = randomOpenWaitDown === YES$1 ? dataList.filter(((item) => item.status === Status_FAVORITE$1)).sort((() => Math.random() - 0.5)) : dataList.filter(((item) => item.status === Status_FAVORITE$1)).sort(((a, b) => b.createDate - a.createDate));
for (let i = 0; i < openCount; i++) {
@@ -14483,7 +14640,7 @@ ${err.stack}` : "");
} else {
$("#reviewsContainer").hide();
$("#reviewsFooter").hide();
- storageManager.saveSettingItem("enableLoadReview", NO);
+ storageManager.saveSettingItem("enableLoadReview", NO$1);
}
}));
$magnets.append(' ');
@@ -15573,7 +15730,7 @@ ${err.stack}` : "");
});
}));
const highlightMagnetPlugin = this.getBean("HighlightMagnetPlugin"),
- enableMagnetsFilter = await storageManager.getSetting("enableMagnetsFilter", NO);
+ enableMagnetsFilter = await storageManager.getSetting("enableMagnetsFilter", NO$1);
if (enableMagnetsFilter === YES$1) {
const savedSettings = await storageManager.getSetting("magnetSortAndFilter", "{}");
let settings;
@@ -15606,7 +15763,7 @@ ${err.stack}` : "");
if ("取消磁力过滤" === $span.text()) {
highlightMagnetPlugin.showAll();
$span.text("排序与过滤");
- storageManager.saveSettingItem("enableMagnetsFilter", NO);
+ storageManager.saveSettingItem("enableMagnetsFilter", NO$1);
} else {
this.openMagnetSortFilterPanel(highlightMagnetPlugin);
}
@@ -15845,7 +16002,7 @@ ${err.stack}` : "");
} else {
highlightMagnetPlugin.showAll();
$("#magnets-span").text("排序与过滤");
- await storageManager.saveSettingItem("enableMagnetsFilter", NO);
+ await storageManager.saveSettingItem("enableMagnetsFilter", NO$1);
}
} catch (e) {
console.error("[磁力排序] 应用失败:", e);
@@ -16895,13 +17052,13 @@ ${err.stack}` : "");
actorCarNumToNameMap: /* @__PURE__ */ new Map(),
actressCarNumToNameMap: /* @__PURE__ */ new Map()
}), t2 = utils.time("组装数据耗时"), settings = {
- showFilterItem: (null == settingObj ? void 0 : settingObj.showFilterItem) ?? NO,
- showFilterActorItem: (null == settingObj ? void 0 : settingObj.showFilterActorItem) ?? NO,
- showFilterKeywordItem: (null == settingObj ? void 0 : settingObj.showFilterKeywordItem) ?? NO,
+ showFilterItem: (null == settingObj ? void 0 : settingObj.showFilterItem) ?? NO$1,
+ showFilterActorItem: (null == settingObj ? void 0 : settingObj.showFilterActorItem) ?? NO$1,
+ showFilterKeywordItem: (null == settingObj ? void 0 : settingObj.showFilterKeywordItem) ?? NO$1,
showFavoriteItem: (null == settingObj ? void 0 : settingObj.showFavoriteItem) ?? YES$1,
showHasDownItem: (null == settingObj ? void 0 : settingObj.showHasDownItem) ?? YES$1,
showHasWatchItem: (null == settingObj ? void 0 : settingObj.showHasWatchItem) ?? YES$1,
- showAllItem: (null == settingObj ? void 0 : settingObj.showAllItem) ?? NO,
+ showAllItem: (null == settingObj ? void 0 : settingObj.showAllItem) ?? NO$1,
tagPosition: (null == settingObj ? void 0 : settingObj.tagPosition) || "rightTop",
movieShowType: (null == settingObj ? void 0 : settingObj.movieShowType) || "hide"
};
@@ -16930,7 +17087,7 @@ ${err.stack}` : "");
foundKeyword = filterKeywordList.find(((kw) => title.includes(kw) || carNum2.startsWith(kw))),
isFilterKeyword = !!foundKeyword;
if (!isSearchPage) {
- let shouldHide = settings.showFavoriteItem === NO && isFavorite || settings.showHasDownItem === NO && isHasDown || settings.showHasWatchItem === NO && isHasWatch || settings.showFilterItem === NO && isFiltered && !(isFavorite || isHasDown || isHasWatch) || settings.showFilterActorItem === NO && isFilterActor || settings.showFilterKeywordItem === NO && isFilterKeyword;
+ let shouldHide = settings.showFavoriteItem === NO$1 && isFavorite || settings.showHasDownItem === NO$1 && isHasDown || settings.showHasWatchItem === NO$1 && isHasWatch || settings.showFilterItem === NO$1 && isFiltered && !(isFavorite || isHasDown || isHasWatch) || settings.showFilterActorItem === NO$1 && isFilterActor || settings.showFilterKeywordItem === NO$1 && isFilterKeyword;
if ($box2.attr("data-movieShowType") !== settings.movieShowType) {
$box2.css("border", "");
$box2.children().css("visibility", "");
@@ -17109,7 +17266,7 @@ ${err.stack}` : "");
}
async parseActressName(url) {
let actorName = null;
- if (await storageManager.getSetting("enableSaveActressCarInfo", NO) === YES$1) {
+ if (await storageManager.getSetting("enableSaveActressCarInfo", NO$1) === YES$1) {
clog.debug("鉴定补录演员信息-已启用, 开始解析详情页");
clog.debug("开始解析演员详情页", url);
const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html);
@@ -17130,7 +17287,7 @@ ${err.stack}` : "");
this.favoriteHotKey = settingObj.favoriteHotKey;
this.hasDownHotKey = settingObj.hasDownHotKey;
this.hasWatchHotKey = settingObj.hasWatchHotKey;
- this.enableImageHotKey = settingObj.enableImageHotKey || NO;
+ this.enableImageHotKey = settingObj.enableImageHotKey || NO$1;
this.clogHotKey = settingObj.clogHotKey;
this.foldCategoryHotKey = settingObj.foldCategoryHotKey;
this.showFilterItemHotKey = settingObj.showFilterItemHotKey;
@@ -17151,7 +17308,7 @@ ${err.stack}` : "");
}, registerToggleHotkey = (hotkeyName, settingKey) => {
const hotkeyString = this[hotkeyName];
hotkeyString && HotkeyManager.registerHotkey(hotkeyString, (async (event) => {
- const newVal = await storageManager.getSetting(settingKey) === YES$1 ? NO : YES$1;
+ const newVal = await storageManager.getSetting(settingKey) === YES$1 ? NO$1 : YES$1;
await storageManager.saveSettingItem(settingKey, newVal);
window.refresh();
}));
@@ -17159,7 +17316,7 @@ ${err.stack}` : "");
for (const hotkeyName in HOTKEY_REGISTRY) if (HOTKEY_REGISTRY.hasOwnProperty(hotkeyName)) {
registerToggleHotkey(hotkeyName, HOTKEY_REGISTRY[hotkeyName]);
}
- if (this.enableImageHotKey === NO) return;
+ if (this.enableImageHotKey === NO$1) return;
const handleAction = async (boxInfo, status) => {
setTimeout((async () => {
let actorName = await this.parseActressName(boxInfo.url);
@@ -17235,7 +17392,7 @@ ${err.stack}` : "");
replaceWithHdForDMM(img);
}));
}
- storageManager.getSetting("hoverBigImg", NO).then(((hoverBigImg) => {
+ storageManager.getSetting("hoverBigImg", NO$1).then(((hoverBigImg) => {
hoverBigImg === YES$1 && (window.imageHoverPreviewObj ? window.imageHoverPreviewObj.bindEvents() : window.imageHoverPreviewObj = new ImageHoverPreview({
selector: this.getSelector().coverImgSelector
}));
diff --git a/javbus.html b/javbus.html
new file mode 100644
index 0000000..25b83cc
--- /dev/null
+++ b/javbus.html
@@ -0,0 +1,993 @@
+
+
+
+
+
+
+
+ NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - JavBus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ 搜尋中...
+ |
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒
+
+
+ 
+
+
+
+
+
+
+ 磁力連結投稿
+
+
+
+
+
+
+ | 磁力名稱 |
+ 檔案大小 |
+ 分享日期 |
+
+
+
+
+
+
+
+
+ |
+
+ 讀取中...
+ |
+
+
+
+
+
+
+
+ 樣品圖像
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 同類影片
+
+
+
+
+
+ 論壇熱帖
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/javdb.html b/javdb.html
new file mode 100644
index 0000000..4f35789
--- /dev/null
+++ b/javdb.html
@@ -0,0 +1,1248 @@
+
+
+
+ SMRA-005 愛人HUNT◇ 逆ナンTRIP!! 私のラブパートナー本気で探します 笹倉彩 (BOD) | JavDB
+ 成人影片數據庫
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 如果你所在國家沒有網絡審查, 请直接訪問 javdb.com
+
+ 1. 安裝官方App,通過關於界面查看最新網址
+ 2. 關注telegram官方頻道: @javdbnews
+ 3. 使用代理軟體訪問 javdb.com 查看首頁公告中的最新網址
+
+
+ 如以上方式獲取的網址是舊的,說明新網址還未更新,請耐心等待1小時後再試
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 識別演員
+
+
+ 識別影片
+
+
+
+
+
+
+
+
+
+ SMRA-005
+ 愛人HUNT◇ 逆ナンTRIP!! 私のラブパートナー本気で探します 笹倉彩
+ (BOD)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 聲明
+ - 本網站的所有磁鏈都來自網友的共享,如果影片沒有磁鏈,請耐心等待網友共享。
+
+ - 使用迅雷下載時,如遇到鏈接被舉報無法下載,請使用115、比特球等離線下載工具進行下載。
+ - 年代久遠的磁鏈會因爲無人供種而無法使用P2P方式下載,請嘗試使用網盤的離線下載。
+
+
+
+
+ 離線下載:
+ - 115和比特球因為蘋果平台限制,iOS版可通過其官方微信小程序添加磁鏈。
+ - 部分含有成人關鍵字的磁鏈會被迅雷進行資源審查導致無法下載。
+ - 大多數狀況下,磁鏈包含的文件數越少,離線成功率越高。
+
+
+
+ BT(P2P)客戶端:
+ 添加
+ 推薦的tracker伺候器列表到客戶端會加快下載速度(部分伺候器在大陸地區需要代理網路輔助連接)。
+
+
+
+
+
+
+
+ | 名稱 |
+ 免費? |
+ 離線? |
+ 線上觀看? |
+ 无廣告? |
+ 審查? |
+
+
+
+
+ 115
+ 網盤
+ |
+ 否 |
+ 是 |
+ 是 |
+ 是 |
+ 否 |
+
+
+ pikpak
+ 網盤
+ |
+ 否 |
+ 是 |
+ 是 |
+ 是 |
+ 否 |
+
+
+ 比特球
+ 網盤
+ |
+ 否 |
+ 是 |
+ 是 |
+ 是 |
+ 否 |
+
+
+ qBittorrent
+ P2P下載 |
+ 是 |
+ 否 |
+ 否 |
+ 是 |
+ 否 |
+
+
+
+ qBittorrent
+ 增強版
+ P2P下載 |
+ 是 |
+ 否 |
+ 否 |
+ 是 |
+ 否 |
+
+
+ VUZE
+ P2P下載 |
+ 是 |
+ 否 |
+ 邊下邊播 |
+ 否 |
+ 否 |
+
+
+ μTorrent
+ P2P下載 |
+ 是 |
+ 否 |
+ 否 |
+ 否 |
+ 否 |
+
+
+ Soda Player
+ P2P播放器(只支持桌面端)
+ |
+ 是 |
+ 否 |
+ 邊下邊播 |
+ 是 |
+ 否 |
+
+
+ 迅雷
+ (Android版)
+ 下載工具 |
+ 是 |
+ 是 |
+ 邊下邊播 |
+ 否 |
+ 是 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 读取中...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index bd606a0..2d4527d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jhs-enhance",
- "version": "3.3.15",
+ "version": "3.3.16",
"description": "Jav-鉴黄师 油猴脚本 - 工程化版本",
"type": "module",
"scripts": {
diff --git a/src/plugins/setting.js b/src/plugins/setting.js
index 64b38cf..51981c0 100644
--- a/src/plugins/setting.js
+++ b/src/plugins/setting.js
@@ -94,9 +94,15 @@ class SettingPlugin extends BasePlugin {
option.canSelect && (videoQualityHtml += ` `);
}));
const coverButtonPlugin = this.getBean("CoverButtonPlugin");
- let settingHtml = `\n \n \n \n \n \n \n
+ let settingHtml = `\n \n \n \n \n \n \n \n
- \n \n \n \n \n \n \n \n \x3c!-- 阿里云盘面板 --\x3e\n \n \n \n \n \n \n \n \n \n refresh_token:\n \n \n \n \n \n
\n \n \n WebDav备份\n \n \n \n \n \n \n \n \n \n \n \n \x3c!-- 基础设置面板 --\x3e\n \n \n 已鉴定标签展示位置:\n \n \n \n \n \n \n 已鉴定内容处理方式:\n \n \n \n \n \n \n \n 鉴定补录演员信息 ❓\n \n \n \n \n \n \n
\n \n \n \n 列表页功能按钮\n \n \n \n \n \n \n \n \n 打开待鉴定|已收藏 窗口数:\n \n \n \n \n \n \n \n \n
\n \n \n \n 封面快捷按钮\n \n \n \n \n \n ${coverButtonPlugin.screenSvg}长缩略图:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.videoSvg}预览视频:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.handleSvg}鉴定按钮:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.siteSvg}第三方跳转:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.copySvg}复制按钮:\n \n \n \n \n \n \n
\n\n \n 预览视频默认画质:\n \n \n \n \n \n \n 评论区条数:\n \n \n \n \n \n \n \n 高亮已收藏演员 ❓\n \n \n \n \n \n \n \n\n
\n \n \n 请求超时时间(毫秒):\n \n \n \n \n \n \n \n
\n \n \n \n 启用控制台日志:\n \n \n \n \n \n\n \n \n \n \x3c!-- 定时任务 --\x3e\n \n \n \n \n 请求间隔时间(毫秒):\n \n \n \n \n \n
\n \n \n 自动检测屏蔽黑名单演员\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n 检测规则:\n \n \n \n \n \n \n \n 自动同步已收藏的演员\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n \n \n 自动检测已收藏演员的最新作品\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n 检测规则:\n \n \n \n \n \n \n \n \x3c!-- 域名设置面板 --\x3e\n \n \n 域名 - MissAv:\n \n \n \n \n \n 域名 - Jable:\n \n \n \n \n \n 域名 - JavTrailer:\n \n \n \n \n \n 域名 - 123Av:\n \n \n \n \n \n 域名 - JavDb:\n \n \n \n \n \n 域名 - JavBus:\n \n \n \n \n \n 域名 - SupJav:\n \n \n \n \n \n \n \x3c!-- 标记删除 --\x3e
+ \n \n \n \n \n \n \n \n \x3c!-- 阿里云盘面板 --\x3e\n \n \n \n \n \n \n \n \n \n refresh_token:\n \n \n \n \n \n
\n \n \n WebDav备份\n \n \n \n \n \n \n \n \n \n \n \n \x3c!-- 基础设置面板 --\x3e\n \n \n 已鉴定标签展示位置:\n \n \n \n \n \n \n 已鉴定内容处理方式:\n \n \n \n \n \n \n \n 鉴定补录演员信息 ❓\n \n \n \n \n \n \n
\n \n \n \n 列表页功能按钮\n \n \n \n \n \n \n \n \n 打开待鉴定|已收藏 窗口数:\n \n \n \n \n \n \n \n \n
\n \n \n \n 封面快捷按钮\n \n \n \n \n \n ${coverButtonPlugin.screenSvg}长缩略图:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.videoSvg}预览视频:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.handleSvg}鉴定按钮:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.siteSvg}第三方跳转:\n \n \n \n \n \n \n \n \n ${coverButtonPlugin.copySvg}复制按钮:\n \n \n \n \n \n \n
\n\n \n 预览视频默认画质:\n \n \n \n \n \n \n 评论区条数:\n \n \n \n \n \n \n \n 高亮已收藏演员 ❓\n \n \n \n \n \n \n \n\n
\n \n \n 请求超时时间(毫秒):\n \n \n \n \n \n \n \n
\n \n \n \n 启用控制台日志:\n \n \n \n \n \n\n \n \n \n \x3c!-- 定时任务 --\x3e\n \n \n \n \n 请求间隔时间(毫秒):\n \n \n \n \n \n
\n \n \n 自动检测屏蔽黑名单演员\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n 检测规则:\n \n \n \n \n \n \n \n 自动同步已收藏的演员\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n \n \n 自动检测已收藏演员的最新作品\n \n \n 任务开关: ❓ \n \n \n \n \n \n \n 任务间隔时间:\n \n \n \n \n \n 检测规则:\n \n \n \n \n \n \n \n \x3c!-- 离线配置面板 --\x3e\n \n \n 115离线文件夹命名\n \n \n 启用自定义格式:\n \n \n \n \n \n \n \n 可用变量(\${} 形式): \n code - 完整番号(如 ABC-123)
+ title - 作品标题
+ maker - 片商
+ actor - 演员(多演员只取第一个)
+ date - 当前日期(YYYY-MM-DD)
+ 例: \${actor}/\${code} = 演员目录下的番号子目录
+ 支持 / 分隔的多级目录,离线文件下载到最末级子目录 \n \n \n \n\n \x3c!-- 域名设置面板 --\x3e\n \n \n 域名 - MissAv:\n \n \n \n \n \n 域名 - Jable:\n \n \n \n \n \n 域名 - JavTrailer:\n \n \n \n \n \n 域名 - 123Av:\n \n \n \n \n \n 域名 - JavDb:\n \n \n \n \n \n 域名 - JavBus:\n \n \n \n \n \n 域名 - SupJav:\n \n \n \n \n \n \n \x3c!-- 标记删除 --\x3e
标记删除列表
@@ -216,6 +222,8 @@ class SettingPlugin extends BasePlugin {
})).on("keydown", (event => this.handleHotkeyInput(event, $element)));
}));
$("#enableImageHotKey").prop("checked", !!settingObj.enableImageHotKey && settingObj.enableImageHotKey === YES);
+ $("#enable115OfflineFormat").prop("checked", !!settingObj.enable115OfflineFormat && settingObj.enable115OfflineFormat === YES);
+ $("#offlineFolderFormat").val(settingObj.offlineFolderFormat || "");
}
handleHotkeyInput(event, $input) {
event.preventDefault();
@@ -624,6 +632,8 @@ class SettingPlugin extends BasePlugin {
settingObj[containerId] = $(`#${containerId}`).val();
}));
settingObj.enableImageHotKey = $("#enableImageHotKey").is(":checked") ? YES : NO;
+ settingObj.enable115OfflineFormat = $("#enable115OfflineFormat").is(":checked") ? YES : NO;
+ settingObj.offlineFolderFormat = $("#offlineFolderFormat").val();
await storageManager.saveSetting(settingObj);
let reviewKeywordList = [];
$("#reviewKeywordContainer .keyword-label").toArray().forEach((item => {
diff --git a/src/plugins/wangpan-115-task.js b/src/plugins/wangpan-115-task.js
index f4506a1..9213a2d 100644
--- a/src/plugins/wangpan-115-task.js
+++ b/src/plugins/wangpan-115-task.js
@@ -80,7 +80,105 @@ class WangPan115TaskPlugin extends BasePlugin {
$headerRow.append($(" ").text("操作"));
}
}
+
+ static sanitizeDirName(str) {
+ if (!str) return "";
+ return str.replace(/[\\/:*?"<>|]/g, "").replace(/\s+/g, " ").trim();
+ }
+
+ static parseOfflineDirTemplate(str, params) {
+ if (!str || !params) return str;
+ return str.replace(/\$\{(\w+)\}/g, (match, key) => {
+ if (!params.hasOwnProperty(key)) return match;
+ const value = params[key] || "";
+ return WangPan115TaskPlugin.sanitizeDirName(String(value));
+ });
+ }
+
+ static async ensureDir(dirName, pid = 0) {
+ const result = await gmHttp.postFileFormData("https://webapi.115.com/files/add", {
+ pid: pid,
+ cname: dirName
+ });
+ if (result && result.file_id) return result.file_id;
+ const searchRes = await searchFiles(dirName, 0, 1, {fc: 1});
+ if (searchRes && searchRes.data && searchRes.data.length > 0) {
+ const match = searchRes.data.find(d => d.pid === pid || d.pid === String(pid));
+ if (match) return match.fid || match.file_id;
+ }
+ return null;
+ }
+
+ static async registerDirAsDownPath(fileId, dirName) {
+ await gmHttp.postFileFormData("https://webapi.115.com/offine/downpath", {
+ file_id: fileId
+ });
+ const list = await getDownPathList();
+ const created = list ? list.find(d => d.file_id === fileId || String(d.file_id) === String(fileId)) : null;
+ return created ? created.id : null;
+ }
+
+ static async createMultiLevelDownPath(templatePath) {
+ const segments = templatePath.split("/").filter(s => s.trim());
+ if (segments.length === 0) return null;
+ let pid = 0;
+ let fileId = null;
+ for (const seg of segments) {
+ fileId = await WangPan115TaskPlugin.ensureDir(seg.trim(), pid);
+ if (!fileId) {
+ console.error("[115离线] 创建目录失败:", seg);
+ return null;
+ }
+ pid = fileId;
+ }
+ const lastDirName = segments[segments.length - 1].trim();
+ const downPathId = await WangPan115TaskPlugin.registerDirAsDownPath(fileId, lastDirName);
+ console.log("[115离线] 多级目录创建完成:", templatePath, "→ downPathId=" + downPathId);
+ return downPathId;
+ }
+
+ getPageInfoForOffline() {
+ const baseInfo = this.getPageInfo();
+ const carNum = baseInfo.carNum || "";
+ let title = "", maker = "", actor = "";
+ if (isJavBus) {
+ title = $("h3").first().text().trim();
+ maker = $('span.header:contains("製作商:")').parent("p").text().replace("製作商:", "").trim() ||
+ $('span.header:contains("制作商:")').parent("p").text().replace("制作商:", "").trim();
+ const actorEl = $('span.genre a[href*="/star/"]').first();
+ actor = actorEl.length ? actorEl.text().trim() : "";
+ } else {
+ title = $(".current-title").first().text().trim() || $("h2.title.is-4 .current-title").first().text().trim() || $(".movie-title").first().text().trim();
+ maker = $('strong:contains("片商:")').parent().find(".value").text().trim() ||
+ $('strong:contains("片商:")').parent().find(".value").text().trim();
+ actor = $('.actor-female').first().text().trim() || $('strong:contains("演員:"), strong:contains("演员:")').parent().find('.value a').first().text().trim() || "";
+ }
+ const now = new Date();
+ if (carNum && title) {
+ const upperTitle = title.toUpperCase();
+ const upperCode = carNum.toUpperCase();
+ if (upperTitle.startsWith(upperCode)) {
+ title = title.substring(carNum.length).replace(/^[\s\-_]+/, "").trim();
+ }
+ }
+ console.log("[115离线] 页面信息提取:", {code: carNum, title, maker, actor});
+ return {
+ code: carNum,
+ title: title,
+ maker: maker,
+ actor: actor,
+ date: utils.formatDate(now).split(" ")[0]
+ };
+ }
async getSavePathId(nyName) {
+ const enableCustom = await storageManager.getSetting("enable115OfflineFormat", NO);
+ if (enableCustom === YES) {
+ const template = await storageManager.getSetting("offlineFolderFormat", "");
+ if (template && template.includes("${")) {
+ const pageInfo = this.getPageInfoForOffline();
+ return WangPan115TaskPlugin.parseOfflineDirTemplate(template, pageInfo);
+ }
+ }
let savePath115 = await storageManager.getSetting("savePath115", "云下载");
nyName && (savePath115 = savePath115.replaceAll("{ny}", nyName));
savePath115 = savePath115.replaceAll("{date}", utils.formatDate(new Date));
@@ -101,7 +199,35 @@ class WangPan115TaskPlugin extends BasePlugin {
});
return;
}
- const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId(), result = await (async (magnet, wp_path_id = "", uid, sign, time) => {
+ const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId();
+
+ let wp_path_id = savePath || "";
+ if (!wp_path_id) {
+ const fullPath = await this.getSavePathId();
+ console.log("[115离线] 目录模板解析结果:", fullPath);
+ if (fullPath) {
+ if (fullPath.includes("/")) {
+ console.log("[115离线] 检测到多级目录,逐级创建:", fullPath);
+ const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
+ if (newId) wp_path_id = newId;
+ } else {
+ const downPathList = await getDownPathList();
+ if (downPathList && downPathList.length > 0) {
+ const matched = downPathList.find((d => d.name === fullPath));
+ if (matched) {
+ wp_path_id = matched.id;
+ console.log("[115离线] 目录匹配结果: 匹配到 \"" + matched.name + "\" -> id=" + matched.id);
+ } else {
+ console.log("[115离线] 目录匹配结果: 未匹配到 \"" + fullPath + "\",自动创建并注册");
+ const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
+ if (newId) wp_path_id = newId;
+ }
+ }
+ }
+ }
+ }
+
+ const result = await (async (magnet, wp_path_id = "", uid, sign, time) => {
const data = {
url: encodeURIComponent(magnet),
wp_path_id: wp_path_id,
@@ -110,7 +236,7 @@ class WangPan115TaskPlugin extends BasePlugin {
time: time
};
return await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=add_task_url", data);
- })(magnetLink, savePath || "", userId, sign, time);
+ })(magnetLink, wp_path_id, userId, sign, time);
console.log("离线下载返回值:", result);
let infoHash = result.info_hash, fileId = await this.getFileId(userId, sign, time, infoHash), openUrl = "https://115.com/?tab=offline&mode=wangpan";
fileId && (openUrl = `https://115.com/?cid=${fileId}&offset=0&mode=wangpan`);
diff --git a/vite.config.mjs b/vite.config.mjs
index 116e411..d649359 100644
--- a/vite.config.mjs
+++ b/vite.config.mjs
@@ -8,7 +8,7 @@ export default defineConfig({
userscript: {
name: 'JHS-enhance',
namespace: 'JHS-enhance',
- version: '3.3.15',
+ version: '3.3.16',
author: 'xiebro,fireinrain',
description: 'Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers',
license: 'MIT',
| |