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
\n
使用115App扫码登录 \n
\n \n
\n
\n \n
\n \n
\n \n
\n 二维码占位区域\n
\n \n \n
\n
已有Cookie? 在此输入并回车\n
\n \n
\n
\n
\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
${cookieValue}
\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 | 115匹配 | \n
\n \n | 名称 | \n 大小 | \n 时间 | \n 播放 | \n
\n \n \n \n
\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 | ${match.name} | \n ${this.formatSize(match.size)} | \n ${match.createTime} | \n \n 播放\n | \n
\n `)).join("")}\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 };