您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
用于基于 mTorrent PT 站 (M-Team) 的辅助脚本
// ==UserScript== // @name mTorrent (M-Team) PT Helper // @name:zh-CN mTorrent (M-Team) PT 助手 // @namespace https://greasyfork.org/zh-CN/users/163820-ysc3839 // @description Helper script for mTorrent based PT sites (M-Team) // @description:zh-CN 用于基于 mTorrent PT 站 (M-Team) 的辅助脚本 // @version 1.3.2 // @author ysc3839 // @license MIT // @match https://kp.m-team.cc/* // @match https://test2.m-team.cc/* // @run-at document-idle // @grant none // ==/UserScript== // This file is built from https://github.com/ysc3839/mTorrent-PT-Helper DO NOT EDIT. // Icon svgs are from https://github.com/ant-design/ant-design-icons Licensed unser MIT LICENSE. // jsx.ts function E(tag, attr, ...nodes) { const ns = attr?.xmlns, e = tag ? ns ? document.createElementNS(ns, tag) : document.createElement(tag) : new DocumentFragment(); if (attr) { delete attr.xmlns; for (const k in attr) { const v = attr[k]; if (typeof v === "function") { e.addEventListener(k, v); } else { e.setAttribute(k, v); } } } e.append(...nodes.flat()); return e; } // icons.tsx var xmlns = "http://www.w3.org/2000/svg"; var Copy = () => E("span", { role: "img", "aria-label": "copy", class: "anticon anticon-copy" }, E("svg", { xmlns, viewBox: "64 64 896 896", focusable: "false", "data-icon": "copy", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" }, E("path", { xmlns, d: "M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z" }))); var Loading = () => E("span", { role: "img", "aria-label": "loading", class: "anticon anticon-loading anticon-spin" }, E("svg", { xmlns, viewBox: "0 0 1024 1024", focusable: "false", "data-icon": "loading", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" }, E("path", { xmlns, d: "M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z" }))); var Check = () => E("span", { role: "img", "aria-label": "check", class: "anticon anticon-check" }, E("svg", { xmlns, viewBox: "64 64 896 896", focusable: "false", "data-icon": "check", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" }, E("path", { xmlns, d: "M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" }))); var ArrowUp = () => E("span", { role: "img", "aria-label": "arrow-up", class: "anticon anticon-arrow-up" }, E("svg", { xmlns, viewBox: "64 64 896 896", focusable: "false", "data-icon": "arrow-up", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" }, E("path", { xmlns, d: "M868 545.5L536.1 163a31.96 31.96 0 00-48.3 0L156 545.5a7.97 7.97 0 006 13.2h81c4.6 0 9-2 12.1-5.5L474 300.9V864c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V300.9l218.9 252.3c3 3.5 7.4 5.5 12.1 5.5h81c6.8 0 10.5-8 6-13.2z" }))); var ArrowDown = () => E("span", { role: "img", "aria-label": "arrow-down", class: "anticon anticon-arrow-down" }, E("svg", { xmlns, viewBox: "64 64 896 896", focusable: "false", "data-icon": "arrow-down", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true" }, E("path", { xmlns, d: "M862 465.3h-81c-4.6 0-9 2-12.1 5.5L550 723.1V160c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v563.1L255.1 470.8c-3-3.5-7.4-5.5-12.1-5.5h-81c-6.8 0-10.5 8.1-6 13.2L487.9 861a31.96 31.96 0 0048.3 0L868 478.5c4.5-5.2.8-13.2-6-13.2z" }))); // content.ts function addStyle(style) { const s = document.createElement("style"); s.textContent = style; document.head.appendChild(s); } var specialClass; function waitForContent() { const e = document.getElementsByClassName("mx-auto")[0]; if (e) return Promise.resolve(e); return new Promise((resolve) => { const root = document.getElementById("root"); new MutationObserver(function(records) { for (const r of records) { for (const n of r.addedNodes) { if (n.nodeType === Node.ELEMENT_NODE && n.id === "app-content") { this.disconnect(); for (const c of n.classList) { if (c.startsWith("css-")) { specialClass = c; break; } } const e2 = n.getElementsByClassName("mx-auto")[0]; resolve(e2); return; } } } }).observe(root, { childList: true }); }); } // api.ts var apiUrls = (() => { let urls = []; try { urls = _APIHOSTS.map((u) => new URL(u)); } catch (e) { console.warn("get _APIHOSTS error:", e); } urls.push(new URL(location.origin + "/api")); return urls; })(); function isApiUrlWithPath(u, path) { for (const a of apiUrls) { if (u.origin === a.origin && u.pathname === a.pathname + path) return true; } return false; } function getApiUrl() { return localStorage.getItem("apiHost") || apiUrls[Math.random() * apiUrls.length | 0].href; } function getAuth() { return localStorage.getItem("auth"); } function getVisitorId() { return localStorage.getItem("visitorId"); } function getDid() { return localStorage.getItem("did"); } function getApiFetchOptions() { return { method: "POST", headers: { authorization: getAuth(), visitorId: getVisitorId(), did: getDid(), ts: Math.floor(Date.now() / 1e3) } }; } async function genDlToken(id) { const f = new FormData(); f.set("id", id); const opts = getApiFetchOptions(); opts.body = f; const res = await fetch(getApiUrl() + "/torrent/genDlToken", opts); const data = await res.json(); if (data.code !== "0") { console.error("genDlToken API error:", data); return null; } return data.data; } async function getTorrentPeers(id) { const f = new FormData(); f.set("id", id); const opts = getApiFetchOptions(); opts.body = f; const res = await fetch(getApiUrl() + "/torrent/peers", opts); const data = await res.json(); if (data.code !== "0") { console.error("getTorrentPeers API error:", data); return null; } return data.data; } // keystate.ts var modifierState = false; (() => { const onkey = (e) => { if (!e.repeat) { modifierState = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey; } }; document.addEventListener("keydown", onkey); document.addEventListener("keyup", onkey); })(); // animation.ts function waitAnimationFrame() { return new Promise((r) => requestAnimationFrame(r)); } function waitAnimationEnd(e) { return new Promise((resolve) => { const onEnd = () => { e.removeEventListener("transitionend", onEnd, true); e.removeEventListener("animationend", onEnd, true); resolve(); }; e.addEventListener("transitionend", onEnd, true); e.addEventListener("animationend", onEnd, true); }); } async function doAnimation(e, name, enter) { const origCls = e.className; const dir = enter ? "enter" : "leave"; const animCls = origCls + ` ${name} ${name}-${dir} ${name}-${dir}-`; e.className = animCls + "prepare"; await waitAnimationFrame(); e.className = animCls + "start"; await waitAnimationFrame(); e.className = animCls + "active"; await waitAnimationEnd(e); e.className = origCls; } // dropdown.tsx addStyle(`:where(.my-ant-menu-override).ant-menu { --ant-menu-item-height: 1.5714285714285714; /* var(--ant-line-height); */ box-sizing: border-box; position: fixed; } :where(.my-ant-menu-override).ant-menu-submenu-popup .ant-menu-vertical >.ant-menu-item { height: var(--ant-menu-item-height); line-height: var(--ant-menu-item-height); } :where(.my-ant-menu-override).ant-menu-submenu-popup .ant-menu-vertical .ant-menu-item { padding: 5px 12px; /* var(--ant-dropdown-padding-block) var(--ant-control-padding-horizontal); */ margin: 0; width: auto; } :where(.my-ant-menu-override).ant-menu-submenu-popup .ant-menu-vertical.ant-menu-sub { min-width: auto; padding: 4px !important; /* var(--ant-padding-xxs) */ } :where(.my-ant-menu-override).ant-menu .ant-menu-item-divider { height: 1px; margin-block: 4px !important; /* var(--ant-margin-xxs) */ }`); function addDropdownMenu(target, items) { let dropdown; let state = 0 /* Hide */; const win = target.ownerDocument.defaultView; const clickCallback = (callback) => function(ev) { const r = callback.call(this, ev); if (r === false || !ev.defaultPrevented) hide(); return r; }; const create = () => { if (!dropdown) { dropdown = E( "div", { class: `ant-menu ant-menu-css-var ant-menu-light ant-menu-submenu ant-menu-submenu-hidden ant-menu-submenu-popup my-ant-menu-override ${specialClass}` }, E("ul", { class: "ant-menu ant-menu-sub ant-menu-vertical", role: "menu" }, items.map( (i) => ( /*i === null ? <li role="separator" class="ant-menu-item-divider"></li> :*/ // separator unused E("li", { role: "menuitem", tabindex: "-1", class: "ant-menu-item ant-menu-item-only-child", click: clickCallback(i[1]) }, E("span", { class: "ant-menu-title-content" }, i[0])) ) )) ); document.body.appendChild(E("div", null, dropdown)); } }; const show = async () => { state = 3 /* Showing */; const { bottom, left } = target.getBoundingClientRect(); const s = dropdown.style; s.top = bottom + 4 + "px"; s.left = left + "px"; dropdown.classList.remove("ant-menu-submenu-hidden"); await doAnimation(dropdown, "ant-slide-up", true); state = 2 /* Show */; win?.addEventListener("mousedown", onTriggerClose, true); win?.addEventListener("contextmenu", onTriggerClose, true); }; const hide = async () => { state = 1 /* Hiding */; win?.removeEventListener("mousedown", onTriggerClose, true); win?.removeEventListener("contextmenu", onTriggerClose, true); await doAnimation(dropdown, "ant-slide-up", false); dropdown.classList.add("ant-menu-submenu-hidden"); state = 0 /* Hide */; }; const onTriggerClose = (ev) => { if (state === 2 /* Show */ && !dropdown.contains(ev.target)) hide(); }; target.addEventListener("contextmenu", (ev) => { ev.preventDefault(); create(); if (state === 0 /* Hide */) { show(); } else if (state === 2 /* Show */) { hide(); } }); } // tooltip.tsx addStyle(`:where(.my-ant-tooltip-override).ant-tooltip { box-sizing: border-box; top: -9999px; left: -9999px; } :where(.my-ant-tooltip-override).ant-tooltip .ant-tooltip-inner { color: #232222; background-color: #e7e1e0; }`); var Tooltip = class { container; tooltip; inner; constructor() { this.container = E("div", null, this.tooltip = E("div", { class: `ant-tooltip ant-tooltip-hidden ant-tooltip-placement-top my-ant-tooltip-override ${specialClass}`, style: "top: 100px; left: 100px;" }, E("div", { class: "ant-tooltip-content" }, this.inner = E("div", { class: "ant-tooltip-inner", role: "tooltip" })))); document.body.appendChild(this.container); } show(e) { this.tooltip.classList.remove("ant-tooltip-hidden"); const { left, top } = e.getBoundingClientRect(); const { scrollX, scrollY } = window; const s = this.tooltip.style; s.left = left + scrollX + "px"; s.top = top + scrollY - this.tooltip.getBoundingClientRect().height - 4 + "px"; doAnimation(this.tooltip, "ant-zoom-big-fast", true); } async destroy() { await doAnimation(this.tooltip, "ant-zoom-big-fast", false); this.tooltip.classList.add("ant-tooltip-hidden"); this.container.remove(); this.container = this.tooltip = this.inner = void 0; } }; // torrents-table.tsx var TorrentsTableManager = class { type; table; tbodyObserver; rowsCount; peersColIndex; linkColor; linkObserver; peersObserver; constructor() { this.tbodyObserver = new MutationObserver(this.onTbodyChange.bind(this)); this.linkObserver = new MutationObserver(this.onLinkChange.bind(this)); this.peersObserver = new MutationObserver(this.onPeersChange.bind(this)); } set(table, type) { this.tbodyObserver.disconnect(); this.linkObserver.disconnect(); this.type = type; this.table = table; this.peersColIndex = void 0; if (table) { const theadr = table.querySelector("thead > tr"), tbody = table.getElementsByTagName("tbody")[0]; if (theadr && tbody) { const c = theadr.children; this.rowsCount = c.length; if (this.type === 2 /* Rankings */) { for (let i = c.length - 1; i >= 0; --i) { const e = c[i].firstElementChild; if (e && e.getAttribute("color") === "red") { this.peersColIndex = i + 1; break; } } const colgroup = table.getElementsByTagName("colgroup")[0]; colgroup?.prepend(E("col", { style: "width: 42px;" })); } this.modifyPlaceholderColspan(tbody); this.addListSelectHead(theadr, tbody); this.tbodyObserver.observe(tbody, { childList: true }); } } } modifyPlaceholderColspan(tbody) { const td = tbody.querySelector("tr.ant-table-placeholder > td[colspan]"); if (td) ++td.colSpan; } addListSelectHead(theadr, tbody) { let span, loading = false; const button = E( "button", { type: "button", class: `ant-btn ant-btn-default ant-btn-sm ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only ${specialClass}`, click: async function() { if (!loading) { const selected = tbody.getElementsByClassName("ant-table-row-selected"); if (selected.length !== 0) { const setLoading = (l) => { loading = l; this.classList.toggle("ant-btn-loading", l); span.classList.toggle("ant-btn-loading-icon", l); span.replaceChildren(l ? Loading() : Check()); }; const tooltip = new Tooltip(); let count = 0; const total = selected.length; const updateCount = () => { tooltip.inner.textContent = `${count}/${total}`; }; setLoading(true); updateCount(); tooltip.show(this); const urls = []; try { for (const tr of selected) { const url = await genDlToken(tr.dataset.id); urls.push(url); ++count; updateCount(); } } catch (e) { console.error(e); tooltip.inner.textContent = "获取种子链接失败"; } if (!urls.some((i) => !i)) { for (let i = 0; i < 2; ++i) { try { await navigator.clipboard.writeText(urls.join("\n")); break; } catch (e) { alert("页面不在前台,复制失败,按确定再次尝试复制"); await new Promise((r) => setTimeout(r, 0)); } } setLoading(false); tooltip.destroy(); } } } } }, span = E("span", { class: "ant-btn-icon" }, Copy()) ); const select = (all) => { const inputs = tbody.getElementsByClassName("ant-checkbox-input"); const event = new Event("change"); for (const i of inputs) { i.checked = all || !i.checked; i.dispatchEvent(event); } }; addDropdownMenu(button, [ ["全选", select.bind(null, true)], ["反选", select.bind(null, false)] ]); let attr; if (this.type === 1 /* Torrents */) { attr = { class: "border border-solid border-black p-2", style: "width: 42px;" }; } else if (this.type === 2 /* Rankings */) { attr = { class: "ant-table-cell", scope: "col", style: "text-align: center;" }; } theadr.prepend(E("th", attr, button)); } onTbodyChange(records) { for (const r of records) { for (const n of r.addedNodes) { if (n.tagName === "TR" && n.childElementCount === this.rowsCount && n.className !== "ant-table-placeholder") { const a = this.addListSelect(n); this.setPeersLinkAndColor(n, a); this.linkObserver.observe(a, { attributes: true, attributeFilter: ["href"] }); this.replaceDownloadIcon(n); } } } } onLinkChange(records) { for (const r of records) { r.target?.__my_update_id?.(); } } addListSelect(tr) { const origClass = tr.className; tr.style.transition = "background-color .2s"; const a = tr.querySelector('a[href^="/detail/"]'); if (a) { a.__my_dataset_tr = tr; a.__my_update_id = function() { const id = this.getAttribute("href").slice(8); this.__my_dataset_tr.dataset.id = id; const links = this.__my_peers_links; if (links) { const href = `/detail/${id}#peers`; for (const l of links) { l.href = href; } } }; a.__my_update_id(); } let label, span, attr; if (this.type === 1 /* Torrents */) { attr = { class: "border border-solid border-black p-2 ", align: "center" }; } else if (this.type === 2 /* Rankings */) { attr = { class: "ant-table-cell", style: "text-align: center;" }; } tr.prepend(E( "td", attr, label = E("label", { class: `ant-checkbox-wrapper ${specialClass}`, style: "transform: scale(1.5);" }, span = E("span", { class: `ant-checkbox ${specialClass}` }, E("input", { class: "ant-checkbox-input", type: "checkbox", change: function() { const c = this.checked; span.classList.toggle("ant-checkbox-checked", c); label.classList.toggle("ant-checkbox-wrapper-checked", c); if (c) { const l = tr.classList; l.remove("bg-sticky_top", "bg-sticky_normal"); l.add("bg-black/10", "ant-table-row-selected"); } else { tr.className = origClass; } } }), E("span", { class: "ant-checkbox-inner" }))) )); return a; } onPeersChange(records) { const seedersSet = /* @__PURE__ */ new Set(); for (const r of records) { let e = r.target; if (e.nodeType === Node.TEXT_NODE) { e = e.parentElement; } const s = e.__my_linked_seeders; if (s) e = s; seedersSet.add(e); } for (const s of seedersSet) { s.__my_update_color(); } } setPeersLinkAndColor(n, a) { const [seedersTd, leechersTd] = this.getPeersTd(n); if (seedersTd && leechersTd) { const seeders = seedersTd.lastElementChild, leechers = leechersTd.lastElementChild; if (seeders && leechers) { leechers.__my_linked_seeders = seeders; seeders.__my_linked_leechers = leechers; seeders.__my_update_color = function() { const seedersCount = parseInt(this.textContent, 10), leechersCount = parseInt(this.__my_linked_leechers.textContent, 10); if (leechersCount && !Number.isNaN(seedersCount)) { const ratio = seedersCount / leechersCount; let color = ""; if (ratio < 0.025) color = "#ff0000"; else if (ratio < 0.05) color = "#ee0000"; else if (ratio < 0.075) color = "#dd0000"; else if (ratio < 0.1) color = "#cc0000"; else if (ratio < 0.125) color = "#bb0000"; else if (ratio < 0.15) color = "#aa0000"; else if (ratio < 0.175) color = "#990000"; else if (ratio < 0.2) color = "#880000"; else if (ratio < 0.225) color = "#770000"; else if (ratio < 0.25) color = "#660000"; else if (ratio < 0.275) color = "#550000"; else if (ratio < 0.3) color = "#440000"; else if (ratio < 0.325) color = "#330000"; else if (ratio < 0.35) color = "#220000"; else if (ratio < 0.375) color = "#110000"; this.style.color = color; } }; seeders.__my_update_color(); this.peersObserver.observe(seeders, { subtree: true, characterData: true }); this.peersObserver.observe(leechers, { subtree: true, characterData: true }); const id = n.dataset.id; a.__my_peers_links = [ this.addPeersLink(seedersTd, id, seeders, leechers), this.addPeersLink(leechersTd, id, seeders, leechers) ]; } } } getPeersTd(n) { if (!this.peersColIndex && this.type === 1 /* Torrents */) { const c = n.children; for (let i = c.length - 1; i >= 0; --i) { if (c[i].getElementsByClassName("anticon-arrow-down").length !== 0) { this.peersColIndex = i; break; } } } if (!this.peersColIndex) return [void 0, void 0]; const seeders = n.children[this.peersColIndex - 1], leechers = n.children[this.peersColIndex]; return [seeders, leechers]; } addPeersLink(p, id, seeders, leechers) { const c = Array.from(p.children); for (const i of c) { i.remove(); } const a = E("a", { href: `/detail/${id}#peers`, target: "_blank" }, c); if (seeders && leechers) { let loading = false, loadingIcon; a.addEventListener("click", async function(e) { if (!modifierState) { e.preventDefault(); if (!loading) { loading = true; if (!loadingIcon) { loadingIcon = Loading(); this.prepend(loadingIcon); } const peers = await getTorrentPeers(id); if (peers) { let s = 0, l = 0; for (const p2 of peers) { if (p2.left === "0") { ++s; } else { ++l; } } seeders.textContent = s; leechers.textContent = l; loadingIcon.remove(); loadingIcon = null; } loading = false; } } }); } if (this.linkColor) { a.style.color = this.linkColor; p.append(a); } else { p.append(a); a.style.color = this.linkColor = a.computedStyleMap().get("color"); } return a; } replaceDownloadIcon(n) { const i = n.getElementsByClassName("anticon-download")[0]; i?.replaceWith(Copy()); } }; var torrentsTable = new TorrentsTableManager(); function findAndSetTable(n, type) { if (n) { const e = n.querySelector("table"); if (e) { torrentsTable.set(e, type); return true; } } else { torrentsTable.set(void 0, void 0); } } function handleTorrentsTable(records, type) { for (const r of records) { for (const n of r.addedNodes) { if (n.nodeType === Node.ELEMENT_NODE) { if (findAndSetTable(n, type)) return; } } } } // xhr-hook.ts var xhr = XMLHttpRequest; var xhrPrototypeProxy = new Proxy(xhr.prototype, { get(target, prop, receiver) { const v = Reflect.get(...arguments); if (prop === "responseText") { const u = new URL(receiver.responseURL); if (isApiUrlWithPath(u, "/torrent/peers")) { XMLHttpRequest = xhr; const data = JSON.parse(v); if (data.code === "0") { data.data.sort((a, b) => { return parseInt(a.left, 10) - parseInt(b.left, 10); }); return JSON.stringify(data); } } } return v; } }); var xhrProxy = new Proxy(xhr, { construct() { const o = Reflect.construct(...arguments); Object.setPrototypeOf(o, xhrPrototypeProxy); return o; } }); function hookXHR(enable) { XMLHttpRequest = enable ? xhrProxy : xhr; } // detail-page.ts var peersTr; function handlePeersTr(trs, storeTr) { for (let i = trs.length - 1; i >= 0; --i) { const tr = trs[i], labelText = tr.getElementsByClassName("ant-descriptions-item-label")[0]?.textContent; if (labelText === "同伴" || labelText === "Peers") { if (storeTr) peersTr = tr; return tr.getElementsByTagName("button")[0]; } } } function clickButton(button) { hookXHR(true); button.click(); } function hookButtonClick(button) { button.onclick = function() { this.onclick = null; hookXHR(true); }; } function scrollToPeers() { if (peersTr) { peersTr.scrollIntoView({ behavior: "smooth" }); peersTr = null; } } function handleDetailPage(e) { e = e.firstElementChild; if (e?.classList.contains("detail-view")) { const showPeers = location.hash === "#peers"; const tbody = e.querySelector(".ant-descriptions-view > table > tbody"); if (tbody) { const button = handlePeersTr(tbody.children, showPeers); if (button) { if (showPeers) { clickButton(button); setTimeout(scrollToPeers, 1e3); } else { hookButtonClick(button); } } let first = true; const o = new MutationObserver(function(records) { if (first) { first = false; setTimeout(() => { this.disconnect(); scrollToPeers(); }, 1e3); } const button2 = handlePeersTr(tbody.children, showPeers); if (button2 && !showPeers) { hookButtonClick(button2); } }); setTimeout(o.disconnect.bind(o), 1e4); o.observe(tbody, { childList: true }); } } } // intercept-dl.ts navigation.addEventListener("navigate", (e) => { console.log("navigate", e); if (!modifierState && e.cancelable && !e.hashChange && e.navigationType === "push") { const url = e.destination.url, u = new URL(url); if (isApiUrlWithPath(u, "/rss/dl") || isApiUrlWithPath(u, "/rss/dlv2")) { e.preventDefault(); navigator.clipboard.writeText(url).then(() => { alert("复制成功"); }); } } }); // upload-page.tsx var dragging = false; var dragOverlay; function onDragEnter() { if (!dragging) { dragging = true; if (!dragOverlay) { dragOverlay = E("div", { style: `position: fixed; top: 0; left: 0; z-index: 100; width: 100%; height: 100%; color: white; background: #00000080; user-select: none; justify-content: center; align-items: center; display: none;`, dragleave: function() { dragging = false; this.style.display = "none"; }, dragover: function(e) { e.preventDefault(); }, drop: function(e) { e.preventDefault(); dragging = false; this.style.display = "none"; const items = e.dataTransfer?.items; if (items) { let f; for (const i of items) { const entry = i.webkitGetAsEntry(); if (entry?.isFile) { f = i.getAsFile(); break; } } if (f) { const torrentInput = document.getElementById("torrent-input"); if (torrentInput) { const dt = new DataTransfer(); dt.items.add(f); torrentInput.files = dt.files; torrentInput.dispatchEvent(new Event("change", { bubbles: true })); } } } } }, E("div", { style: "pointer-events: none; background: #000a; border-radius: 10px; padding: 10px;" }, E("h1", { style: "margin: 0;" }, "放下以选择该文件"))); document.body.append(dragOverlay); } dragOverlay.style.display = "flex"; } } function enterUploadPage() { addEventListener("dragenter", onDragEnter); } function exitUploadPage() { removeEventListener("dragenter", onDragEnter); } // main.user.tsx addStyle(`#app-content { overflow: unset !important; } @media screen and (max-width: 1380px) { #app-content > div { width: 100% !important; } .mx-auto { margin: 0 !important; } } .braft-output-content { max-height: none !important; overflow-y: auto !important; } .ant-image { background: unset !important; } .ant-image .ant-image-img-placeholder { background: unset !important; }`); function replaceUpDownIcon() { const up = document.querySelector("img.arrowup"), down = document.querySelector("img.arrowdown"); if (up && down) { const upIcon = ArrowUp(), downIcon = ArrowDown(); upIcon.classList.add("text-mt-dark-green"); downIcon.classList.add("text-mt-dark-red"); up.replaceWith(upIcon); down.replaceWith(downIcon); } } function getPageType() { return location.pathname.split("/")[1]; } waitForContent().then((e) => { replaceUpDownIcon(); const page = getPageType(); if (page === "upload") { enterUploadPage(); } else if (page === "browse") { findAndSetTable(e, 1 /* Torrents */); } else if (page === "rankings") { findAndSetTable(e, 2 /* Rankings */); } new MutationObserver(function(records) { const page2 = getPageType(); if (page2 === "upload") { enterUploadPage(); } else { exitUploadPage(); if (page2 === "browse") { handleTorrentsTable(records, 1 /* Torrents */); } else if (page2 === "rankings") { handleTorrentsTable(records, 2 /* Rankings */); } else { findAndSetTable(); if (page2 === "detail") { handleDetailPage(e); } } } }).observe(e, { childList: true }); });