Filtering "Incomplete" for PterClub

支持“非完结”种子主副标题过滤 + 精确识别制作组(仅匹配以 - 开头并出现在标题结尾的情况)

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Filtering "Incomplete" for PterClub
// @namespace    http://tampermonkey.net/
// @version      3.2
// @description  支持“非完结”种子主副标题过滤 + 精确识别制作组(仅匹配以 - 开头并出现在标题结尾的情况)
// @author       @Zuoans
// @match        https://pterclub.com/torrents.php* 
// @license      MIT
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // ====================== 样式定义 ======================
    GM_addStyle(`
        :root {
            --blue-start: rgba(51, 160, 200, 0.6);
            --blue-mid: rgba(51, 160, 200, 0.1);
            --purple-start: rgba(147, 112, 219, 0.5);
            --purple-mid: rgba(147, 112, 219, 0.1);
        }

        /* incomplete样式 */
        table.torrentname > tbody > tr.tm-incomplete:not(.tm-group) {
            background: linear-gradient(to right, var(--blue-start) 0%, var(--blue-mid) 50%, rgba(255,255,255,0) 90%) !important;
        }

        /* 制作组样式 */
        table.torrentname > tbody > tr.tm-group:not(.tm-incomplete) {
            background: linear-gradient(to right, var(--purple-start) 0%, var(--purple-mid) 50%, rgba(255,255,255,0) 90%) !important;
        }

        /* incomplete&制作组双重标记样式 */
        table.torrentname > tbody > tr.tm-incomplete.tm-group {
            background: linear-gradient(to right, var(--purple-start) 0%, var(--purple-mid) 50%, rgba(255,255,255,0) 90%) !important;
        }

        /* 文字保护 */
        table.torrentname [class*="tm-"] td {
            text-shadow: 0 1px 1px rgba(255,255,255,0.1),
                         0 -1px 1px rgba(0,0,0,0.1) !important;
        }
    `);

    // 目标制作组列表(新增 PTerWEB)
    const targetGroups = [
        'AdBlue', 'AREY', 'BdC', 'BMDru', 'CatEDU', 'c0kE',
        'doraemon', 'JKCT', 'KMX', 'Lislander', 'RO',
        'Telesto', 'XPcl', 'ZTR', 'PTerWEB'
    ];

    // 辅助函数:转义正则特殊字符
    function escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[$$\$$]/g, '\\$&');
    }

    // ✅ 制作组正则:只匹配以 - 开头,并出现在标题结尾的组名(如 -ZTR)
    const groupRegex = new RegExp(
        `-(?:${targetGroups.map(g => escapeRegExp(g)).join('|')})(?=[\\s\\W]|$)`, 
        'i'
    );

    // 排除关键词正则(包含 Complete / Fin / FIN+ 的行不能被标记为 non-complete)
    const excludeKeywordRegex = /\b(?:Complete|Fin)(?!\w)|FIN\+/gi;

    // 新增:incomplete 正则(仅检测 SxxExx 或 第X集,不考虑 EP)
    const incompleteRegex = /(?:^|\s)(S\d+E\d+|第\d+集)(?=\s|$)/i;

    function safeHighlight() {
        const rows = document.querySelectorAll('table.torrentname > tbody > tr');

        rows.forEach(tr => {
            tr.classList.remove('tm-incomplete', 'tm-group');

            // 获取主标题
            const titleLink = tr.querySelector('.torrentname a');
            if (!titleLink) return;

            let mainTitle = titleLink.innerText.trim();

            // 获取副标题
            let subTitleEl = tr.querySelector('.torrentname div[style*="margin-top"] span');
            let subTitle = subTitleEl ? subTitleEl.innerText.trim() : '';

            let fullTitle = (mainTitle + ' ' + subTitle).trim();

            // 检查是否包含排除关键词
            const hasExclusion = excludeKeywordRegex.test(fullTitle);

            // 判断是否为非完结(主副标题中任意一个满足即可)
            const isIncomplete = !hasExclusion && incompleteRegex.test(fullTitle);

            // 判断是否为目标制作组(✅ 仅匹配以 - 开头并出现在结尾的组名)
            const isTargetGroup = groupRegex.test(fullTitle);

            if (isIncomplete) tr.classList.add('tm-incomplete');
            if (isTargetGroup) tr.classList.add('tm-group');
        });
    }

    // MutationObserver 设置
    const observer = new MutationObserver(mutations => {
        if (mutations.some(mut => mut.addedNodes.length > 0)) {
            safeHighlight();
        }
    });

    document.addEventListener('DOMContentLoaded', () => {
        safeHighlight();
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });

    // 页面卸载时清理
    window.addEventListener('unload', () => {
        document.querySelectorAll('tr').forEach(el => {
            el.className = el.className.replace(/\btm-\w+\b/g, '');
        });
    });

})();