import { BasePlugin } from '../core/base-plugin.js'; import { __publicField, isJavBus, isJavDb, currentHref, NO } from '../core/constants.js'; import { searchFiles } from './wangpan-115-task.js'; class WangPan115Plugin extends BasePlugin { constructor() { super(...arguments); __publicField(this, "JHS_115_COOKIE", "jhs_115_cookie"); __publicField(this, "JHS_115_MAX_AGE", "jhs_115_max_age"); } getName() { return "WangPan115Plugin"; } async initCss() { return "\n \n "; } async handle() { if (!currentHref.includes("&ac=userfile") && currentHref.includes("115")) { utils.loopDetector((() => $("#js-login-box").length > 0), (() => { if (0 !== $("#js-login-box").length) { this.reLogin(); this.hookPage(); this.bindClick(); } }), 20, 4e3, !0); this.createCookiePanel(); } } reLogin() { utils.loopDetector((() => $(".login-finished").length > 0), (() => { if ($(".login-finished").length > 0 || 0 === $("#js-login-box").length) return; const jhs_115_cookie = localStorage.getItem(this.JHS_115_COOKIE), jhs_115_max_age = localStorage.getItem(this.JHS_115_MAX_AGE); document.cookie.includes("SEID") || null === jhs_115_cookie || utils.q(null, "检测到上次登录已有缓存cookie, 是否使用并登录?", (() => { utils.addCookie(jhs_115_cookie, { maxAge: parseInt(jhs_115_max_age), domain: ".115.com" }); window.location.href = "https://115.com/?cid=0&offset=0&mode=wangpan"; })); }), 20, 1500, !0); } hookPage() { const $cookieTab = $('🔰 JHS-扫码'); $(".ltab-office").after($cookieTab); const $cookieScene = $(`\n \n `); $("#js-login_box").find(".login-footer").before($cookieScene); } bindClick() { $("#jhs-cookie").on("click", (() => { const finishedEl = document.querySelector('[lg_rel="finished"]'); if (finishedEl) finishedEl.style.display = "none"; else { document.querySelector('[lg_rel="qrcode"]').style.display = "none"; document.querySelector(".login-footer").style.display = "none"; document.querySelector(".list-other-login").style.display = "none"; } document.querySelectorAll("#js-login_way > *").forEach((tab => { tab.classList.remove("current"); })); document.querySelector("#jhs_cookie_box").style.display = "block"; $("#jhs-cookie").css("background", "#fff"); $(".ltab-cloud").addClass("change-bg"); })); $(".ltab-cloud").on("click", (() => { document.querySelector("#jhs_cookie_box").style.display = "none"; const finishedEl = document.querySelector('[lg_rel="finished"]'); if (finishedEl) finishedEl.style.display = "flex"; else { document.querySelector('[lg_rel="qrcode"]').style.display = "block"; document.querySelector(".login-footer").style.display = "block"; document.querySelector(".list-other-login").style.display = "block"; } $("#jhs-cookie").css("background", "#F9FAFB"); $(".ltab-cloud").removeClass("change-bg"); })); let loginTimeout = null; $("#login-115-type").on("change", (async event => { let login115Type = $("#login-115-type").val(); if (!login115Type) return; const loginInfo = (await (async loginType => { let url = `https://qrcodeapi.115.com/api/1.0/${loginType}/1.0/token/`; return await gmHttp.get(url); })(login115Type)).data, qrcode = loginInfo.qrcode, sign = loginInfo.sign, time = loginInfo.time, uid = loginInfo.uid; console.log("生成二维码:", loginInfo); const $qrcodeBox = $("#qrcode-box"); $qrcodeBox.css("display", "flex"); $qrcodeBox.html(""); new QRCode($qrcodeBox[0], { text: qrcode, width: 150, height: 150, correctLevel: QRCode.CorrectLevel.H }); loginTimeout && clearTimeout(loginTimeout); const checkLoginRecursive = async () => { try { const loginResult = await (async (uid, time, sign) => { let url = `https://qrcodeapi.115.com/get/status/?uid=${uid}&time=${time}&sign=${sign}`; return await gmHttp.get(url); })(uid, time, sign); console.log("已扫码, 正在获取结果:", loginResult); let data = loginResult.data, msg = data.msg, status = data.status; if (msg) { console.log(msg); show.info(msg); } if (2 === status) { show.ok("扫码登录成功"); const checkResult = await (async (loginType, uid) => { const data = { app: loginType, account: uid }, url = `https://passportapi.115.com/app/1.0/${loginType}/1.0/login/qrcode/`; return await gmHttp.postFileFormData(url, data); })(login115Type, uid); console.log("扫码登录成功:", checkResult); if (checkResult.data && checkResult.data.cookie) { const cookie = checkResult.data.cookie, cookieStr = `UID=${cookie.UID}; CID=${cookie.CID}; SEID=${cookie.SEID}; KID=${cookie.KID}`; console.log("解析出cookie:", cookieStr); localStorage.setItem(this.JHS_115_COOKIE, cookieStr); localStorage.setItem(this.JHS_115_MAX_AGE, $("#cookie-expiry-select").val()); window.location.href = "https://115.com/?cid=0&offset=0&mode=wangpan"; } return; } loginTimeout = setTimeout(checkLoginRecursive, 500); } catch (error) { console.error("登录检查失败:", error); } }; await checkLoginRecursive(); })); const handleCookie = () => { const cookieStr = cookieInput.value, expirySelect = document.getElementById("cookie-expiry-select"); let maxAge = parseInt(expirySelect.value); utils.addCookie(cookieStr, { maxAge: maxAge, domain: ".115.com" }); window.location.href = "https://115.com/?cid=0&offset=0&mode=wangpan"; }, cookieInput = document.getElementById("cookie-str-input"); cookieInput.addEventListener("keydown", (function(event) { if ("Enter" === event.key) { event.preventDefault(); handleCookie(); } })); $("#submit-cookie-btn").on("click", (() => { handleCookie(); })); } showMessage(message) { const toast = document.createElement("div"); toast.textContent = message; toast.style.cssText = "\n position: fixed;\n top: 20px;\n right: 20px;\n background-color: #333;\n color: white;\n padding: 10px 20px;\n border-radius: 5px;\n z-index: 20000;\n opacity: 0;\n transition: opacity 0.5s ease-in-out;\n "; document.body.appendChild(toast); setTimeout((() => { toast.style.opacity = "1"; }), 10); setTimeout((() => { toast.style.opacity = "0"; setTimeout((() => toast.remove()), 500); }), 3e3); } createCookiePanel() { const cookieValue = localStorage.getItem(this.JHS_115_COOKIE); if (!cookieValue) return; const panel = document.createElement("div"); panel.id = "jhs-cookie-panel"; panel.innerHTML = `\n \n \n `; document.body.appendChild(panel); const header = document.getElementById("jhs-cookie-header"); document.getElementById("jhs-cookie-content"); const toggleIcon = document.getElementById("jhs-toggle-icon"), copyButton = document.getElementById("jhs-copy-btn"); header.addEventListener("click", (() => { const isExpanded = panel.classList.toggle("expanded"); toggleIcon.textContent = isExpanded ? "▲" : "▼"; })); copyButton.addEventListener("click", (async e => { e.stopPropagation(); try { await navigator.clipboard.writeText(cookieValue); this.showMessage("Cookie 已成功复制到剪贴板!"); } catch (err) { console.error("Failed to copy text using clipboard API: ", err); const tempTextArea = document.createElement("textarea"); tempTextArea.value = cookieValue; document.body.appendChild(tempTextArea); tempTextArea.select(); document.execCommand("copy"); document.body.removeChild(tempTextArea); this.showMessage("Cookie 已复制! (回退方案)"); } })); panel.classList.remove("expanded"); } } const _WangPan115MatchPlugin = class _WangPan115MatchPlugin extends BasePlugin { constructor() { super(...arguments); __publicField(this, "loginStatus", _WangPan115MatchPlugin.LoginStatus.UNCHECKED); } getName() { return "WangPan115MatchPlugin"; } async initCss() { return "\n \n "; } async handle() { $(document).on("click", ".jhs-match-no-login-btn", (async event => { event.preventDefault(); event.stopPropagation(); await this.handleLoginRedirect(); })); $(document).on("click", ".jhs-match-btn", (event => { event.preventDefault(); event.stopImmediatePropagation(); this.showMatchDetail(event.currentTarget); })); $(document).on("click", ".jhs-match-error-btn", (async event => { event.preventDefault(); event.stopPropagation(); await this.retryMatch(event.currentTarget); })); await this.matchDetailPage(); $(document).on("click", ".jhs-match-detail-error-btn", (async event => { event.preventDefault(); event.stopPropagation(); $(event.currentTarget).replaceWith("匹配中..."); try { const carNum2 = this.getPageInfo().carNum, matchList = await this.searchFiles(carNum2); $(".jhs-115-match-detail").remove(); await this.matchDetailPage(matchList); } catch (error) { console.error(`重新匹配失败 [${carNum}]:`, error); this.showMatchError($box, carNum, error); } })); } async matchDetailPage(matchList) { if (!window.isDetailPage) return; if (await storageManager.getSetting("enable115Match", NO) === NO) return; const $detail = $('\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
115匹配
名称大小时间播放
\n
\n '), $tbody = $detail.find("tbody"); try { const carNum2 = this.getPageInfo().carNum; matchList || (matchList = await this.searchFiles(carNum2)); await this.checkLoginStatus(); if (this.loginStatus === _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT) $tbody.append(`\n 未登录\n `); else if (matchList.length > 0) { const rowsHtml = matchList.map((match => `\n \n ${match.name}\n ${this.formatSize(match.size)}\n ${match.createTime}\n \n 播放\n \n \n `)).join(""); $tbody.append(rowsHtml); } else $tbody.append(`\n 未匹配\n `); } catch (error) { $tbody.append(`\n 加载失败,请重试\n `); console.error("加载文件列表时发生错误:", error); } if (isJavDb) if ($("#all-match-box").length) $("#all-match-box").append($detail); else { $("#tabs-container").before("
"); $("#all-match-box").append($detail); } else $("#mag-submit-show").before($detail); } async matchMovieList(movieListElement) { if (await storageManager.getSetting("enable115Match", NO) !== NO) { await this.checkLoginStatus(); await this.processMovieElements(movieListElement); } else $(".video-title [class^='jhs-match-']").remove(); } showMatchDetail(buttonElement) { const $el = $(buttonElement), matchData = $el.attr("data-match"); $(".jhs-match-detail").remove(); const matches = this.parseMatchData(matchData); if (0 === matches.length) return; if (1 === matches.length) { const pickcode = matches[0].videoId; window.open(`https://115vod.com/?pickcode=${pickcode}&share_id=0`, "_blank"); return; } const $detail = this.createMatchDetailElement(matches); this.positionDetailElement($detail, $el); this.addOutsideClickHandler($detail); $detail.on("click", (e => { e.stopPropagation(); })); } parseMatchData(matchData) { try { return JSON.parse(matchData) || []; } catch (e) { console.error("解析匹配数据失败:", e); return []; } } createMatchDetailElement(matches) { const $detail = $(`\n
\n \n \n \n \n \n \n \n \n \n \n ${matches.map((match => `\n \n \n \n \n \n \n `)).join("")}\n \n
名称大小时间播放
${match.name}${this.formatSize(match.size)}${match.createTime}\n 播放\n
\n
\n `); $("body").append($detail); return $detail; } positionDetailElement($detail, $trigger) { const offset = $trigger.offset(); $detail.css({ top: offset.top - $detail.outerHeight() + 20, left: offset.left }); } addOutsideClickHandler($detail) { setTimeout((() => { $(document).on("click.jhs-match-detail", (e => { if (!$detail.is(e.target) && 0 === $detail.has(e.target).length) { $detail.remove(); $(document).off("click.jhs-match-detail"); } })); }), 100); } async retryMatch(buttonElement) { const $el = $(buttonElement), $box2 = $el.closest(".movie-box, .item"), carNum2 = $el.attr("data-keyword"); $el.replaceWith("匹配中..."); try { const matchList = await this.searchFiles(carNum2); this.updateMatchStatus($box2, carNum2, matchList); } catch (error) { console.error(`重新匹配失败 [${carNum2}]:`, error); this.showMatchError($box2, carNum2, error); } } updateMatchStatus($box2, carNum2, matchList) { if (matchList.length > 0) { $box2.find(".jhs-match-btn").replaceWith(`匹配${matchList.length}个`); const $deleteBtn = $box2.find(".delete115Svg"); if ($deleteBtn.length > 0 && matchList[0].dirId) { $deleteBtn.attr("data-match", JSON.stringify(matchList)); $deleteBtn.show(); } } else { $box2.find(".jhs-match-btn").replaceWith(`未匹配`); const $deleteBtn = $box2.find(".delete115Svg"); if ($deleteBtn.length > 0) { $deleteBtn.removeAttr("data-match"); $deleteBtn.hide(); } } } async handleLoginRedirect() { window.open("https://115.com"); } async searchFiles(carNum2) { var _a2; let searchKeyword = carNum2.toLowerCase().replace("fc2-", ""); return (null == (_a2 = (await searchFiles(searchKeyword)).data) ? void 0 : _a2.map((data => ({ folderId: data.fid, dirId: data.cid, videoId: data.pc, name: data.n, createTime: utils.formatDate(new Date(1e3 * data.te)), size: data.s, isVideo: [ ".mp4", ".avi", ".mov", ".mkv", ".flv", ".wmv" ].some((ext => { var _a3; return null == (_a3 = data.n) ? void 0 : _a3.toLowerCase().endsWith(ext); })) }))).filter((x => x.folderId && x.isVideo && x.name.toLowerCase().includes(searchKeyword)))) || []; } showMatchError($box2, carNum2, error) { $box2.find(".jhs-match-btn").replaceWith(`匹配失败`); show.error(`${carNum2} 匹配失败: ${error.message || "网络错误"}`); } async checkLoginStatus() { var _a2; if (this.loginStatus === _WangPan115MatchPlugin.LoginStatus.UNCHECKED) try { const testResult = await searchFiles("test"); this.loginStatus = (null == (_a2 = testResult.error) ? void 0 : _a2.includes("登录")) ? _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT : _WangPan115MatchPlugin.LoginStatus.LOGGED_IN; } catch { this.loginStatus = _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT; } } async processMovieElements(movieListElement) { const promises = Array.from(movieListElement).filter((ele => !utils.isHidden(ele))).filter((ele => !(isJavBus && $(ele).find(".avatar-box").length > 0))).map((ele => this.processSingleMovieElement(ele))); await Promise.all(promises); } async processSingleMovieElement(element) { const $box2 = $(element), {carNum: carNum2} = this.getBoxCarInfo($box2); if (!($box2.find("[class^='jhs-match-']").length > 0)) if (this.loginStatus !== _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT) try { const matchList = await this.searchFiles(carNum2); this.addTag($box2, carNum2, matchList); } catch (error) { console.error(`搜索失败 [${carNum2}]:`, error); this.addTag($box2, carNum2, []); } else this.addTag($box2, carNum2, []); } addTag($box2, carNum2, matchList) { if (!($box2.find("[class^='jhs-match-']").length > 0)) if (this.loginStatus === _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT) $box2.find(".video-title").prepend(`未登录`); else if (matchList.length > 0) { const title = 1 === matchList.length ? "点击直接播放" : `点击查看${matchList.length}个匹配结果`; $box2.find(".video-title").prepend(`匹配${matchList.length}个`); const $deleteBtn = $box2.find(".delete115Svg"); if ($deleteBtn.length > 0 && matchList[0].dirId) { $deleteBtn.attr("data-match", JSON.stringify(matchList)); $deleteBtn.show(); } } else $box2.find(".video-title").prepend(`未匹配`); } formatSize(bytes) { if (!bytes) return "-"; const units = [ "B", "KB", "MB", "GB", "TB" ]; let size = parseFloat(bytes), unit = 0; for (;size >= 1024 && unit < units.length - 1; ) { size /= 1024; unit++; } return `${size.toFixed(2)} ${units[unit]}`; } }; __publicField(_WangPan115MatchPlugin, "LoginStatus", { UNCHECKED: -1, LOGGED_OUT: 0, LOGGED_IN: 1 }); let WangPan115MatchPlugin = _WangPan115MatchPlugin; export { WangPan115Plugin, WangPan115MatchPlugin };