M-Team 高级搜索助手

在高级搜索区添加「最近1/3/6/12个月热度」以及「1-2/2-3/3-4/4-5/5-10/10-20年前热度」,并提供「全部热度」「取消排名」按钮,自动设定时间范围并按种子数降序排序

// ==UserScript==
// @name         M-Team 高级搜索助手
// @namespace    http://tampermonkey.net/
// @version      4.5.0
// @description  在高级搜索区添加「最近1/3/6/12个月热度」以及「1-2/2-3/3-4/4-5/5-10/10-20年前热度」,并提供「全部热度」「取消排名」按钮,自动设定时间范围并按种子数降序排序
// @author       Zola
// @match        https://next.m-team.cc/browse*
// @grant        none
// @license      MIT
// @run-at       document-idle
// ==/UserScript==

(function () {
'use strict';

const PARAMS = {
SORT: 'sort',
SORT_VALUE: 'seeders:descend',
START_DATE: 'uploadDateStart',
END_DATE: 'uploadDateEnd'
};

function waitForElement(selector) {
return new Promise((resolve) => {
const hit = document.querySelector(selector);
if (hit) return resolve(hit);
const mo = new MutationObserver(() => {
const el = document.querySelector(selector);
if (el) {
mo.disconnect();
resolve(el);
}
});
mo.observe(document.body, { childList: true, subtree: true });
});
}

// 最近 N 个月热度
function createDateSortButton(text, monthsToGoBack) {
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = text;
btn.className = 'ant-btn ant-btn-default';
btn.style.margin = '4px';
btn.addEventListener('click', () => {
const today = new Date();
const past = new Date(today);
past.setMonth(today.getMonth() - monthsToGoBack);

const start = Math.floor(past.getTime() / 1000);
const end = Math.floor(today.getTime() / 1000);

const url = new URL(location.href);
const sp = url.searchParams;
sp.set(PARAMS.SORT, PARAMS.SORT_VALUE);
sp.set(PARAMS.START_DATE, String(start));
sp.set(PARAMS.END_DATE, String(end));
sp.set('pageNumber', '1');
location.href = url.toString();
});
return btn;
}

// 从 X 年前到 Y 年前的区间热度
function createYearRangeSortButton(text, startYearsAgo, endYearsAgo) {
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = text;
btn.className = 'ant-btn ant-btn-default';
btn.style.margin = '4px';
btn.addEventListener('click', () => {
const today = new Date();
const rangeEnd = new Date(today);   // 距今 startYearsAgo(较近)
const rangeStart = new Date(today); // 距今 endYearsAgo(较远)

rangeEnd.setFullYear(today.getFullYear() - startYearsAgo);
rangeStart.setFullYear(today.getFullYear() - endYearsAgo);

const start = Math.floor(rangeStart.getTime() / 1000);
const end = Math.floor(rangeEnd.getTime() / 1000);

const url = new URL(location.href);
const sp = url.searchParams;
sp.set(PARAMS.SORT, PARAMS.SORT_VALUE);
sp.set(PARAMS.START_DATE, String(start));
sp.set(PARAMS.END_DATE, String(end));
sp.set('pageNumber', '1');
location.href = url.toString();
});
return btn;
}

// 全部热度:清除时间,仅排序
function createSortOnlyButton() {
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = '全部热度';
btn.className = 'ant-btn ant-btn-default';
btn.style.margin = '4px';
btn.addEventListener('click', () => {
const url = new URL(location.href);
const sp = url.searchParams;
sp.set(PARAMS.SORT, PARAMS.SORT_VALUE);
sp.delete(PARAMS.START_DATE);
sp.delete(PARAMS.END_DATE);
sp.set('pageNumber', '1');
location.href = url.toString();
});
return btn;
}

// 取消排名:清除排序与时间
function createClearAllButton() {
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = '取消排名';
btn.className = 'ant-btn ant-btn-default';
btn.style.margin = '4px';
btn.addEventListener('click', () => {
const url = new URL(location.href);
const sp = url.searchParams;
sp.delete(PARAMS.SORT);
sp.delete(PARAMS.START_DATE);
sp.delete(PARAMS.END_DATE);
sp.set('pageNumber', '1');
location.href = url.toString();
});
return btn;
}

async function mountOnce() {
const form =
(await waitForElement('form.torrent-search-panel')) ||
(await waitForElement('form.ant-form[class*="torrent-search-panel"]')) ||
(await waitForElement('form.ant-form'));

if (!form || form.dataset.mtBtnsMounted) return;
form.dataset.mtBtnsMounted = '1';

if (document.getElementById('custom-search-buttons-container')) return;

const wrap = document.createElement('div');
wrap.id = 'custom-search-buttons-container';
wrap.className = 'flex flex-wrap items-center';
wrap.style.margin = '10px 0';

// 最近区间(按月)- 使用数字表达
[
{ text: '最近1个月热度', months: 1 },
{ text: '最近3个月热度', months: 3 },
{ text: '最近6个月热度', months: 6 },
{ text: '最近12个月热度', months: 12 }
].forEach((cfg) => wrap.appendChild(createDateSortButton(cfg.text, cfg.months)));

// 按年前区间(热度)
wrap.appendChild(createYearRangeSortButton('1-2年前热度', 1, 2));
wrap.appendChild(createYearRangeSortButton('2-3年前热度', 2, 3));
wrap.appendChild(createYearRangeSortButton('3-4年前热度', 3, 4));
wrap.appendChild(createYearRangeSortButton('4-5年前热度', 4, 5));
wrap.appendChild(createYearRangeSortButton('5-10年前热度', 5, 10));
wrap.appendChild(createYearRangeSortButton('10-20年前热度', 10, 20));

// 全部热度、取消排名
wrap.appendChild(createSortOnlyButton());
wrap.appendChild(createClearAllButton());

form.insertAdjacentElement('afterend', wrap);
}

mountOnce();

const obs = new MutationObserver(() => mountOnce());
obs.observe(document.body, { childList: true, subtree: true });
})();