Greasy Fork

Greasy Fork is available in English.

DMM Top Filter Buttons

Quality buttons append after last found quality with |, ignore duplicates, works in any click order, checks entire input string.

当前为 2025-08-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         DMM Top Filter Buttons
// @namespace    http://tampermonkey.net/
// @version      1.16
// @description  Quality buttons append after last found quality with |, ignore duplicates, works in any click order, checks entire input string.
// @author       Waseem
// @match        https://debridmediamanager.com/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    function setReactValue(element, value) {
        const nativeSetter = Object.getOwnPropertyDescriptor(
            window.HTMLInputElement.prototype, 'value'
        ).set;
        nativeSetter.call(element, value);
        element.dispatchEvent(new Event('input', { bubbles: true }));
    }

    const buttons = [
        { text: 'instantRD',    value: 'videos:>0',              class: 'dmm-instantrd' },
        { text: '4K',           value: '2160p|4k',               class: 'dmm-4k' },
        { text: '1080p',        value: '1080p',                  class: 'dmm-1080p' },
        { text: '720p',         value: '720p',                   class: 'dmm-720p' },
        { text: 'Dolby Vision', value: 'dovi|dv|dolby|vision',   class: 'dmm-dolbyvision' },
        { text: 'HDR',          value: 'hdr',                    class: 'dmm-hdr' },
        { text: 'Remux',        value: 'remux',                  class: 'dmm-remux' }
    ];

    const qualityValues = ['2160p|4k', '1080p', '720p'];

    function addFilterButtons() {
        const container = document.querySelector(
            '#__next > div > div.mb-2.flex.items-center.gap-2.overflow-x-auto.p-2 > div'
        );
        const input = document.querySelector('#query');
        if (!container || !input) return;

        buttons.slice().reverse().forEach(btn => {
            if (container.querySelector(`span.${btn.class}`)) return;

            const span = document.createElement('span');
            span.textContent = btn.text;
            span.className =
                `${btn.class} cursor-pointer whitespace-nowrap rounded border border-blue-500 bg-blue-900/30 px-2 py-0.5 text-xs text-blue-100 transition-colors hover:bg-blue-800/50`;

            container.insertBefore(span, container.firstChild);

            span.addEventListener('click', () => {
                let current = input.value.trim();

                if (qualityValues.includes(btn.value)) {
                    if (current.includes(btn.value)) return; // already present

                    // Find all existing qualities in the input
                    let lastFound = null;
                    qualityValues.forEach(q => {
                        const idx = current.lastIndexOf(q);
                        if (idx !== -1) lastFound = { value: q, index: idx };
                    });

                    if (lastFound) {
                        // Append after the last found quality using |
                        const before = current.slice(0, lastFound.index + lastFound.value.length);
                        const after = current.slice(lastFound.index + lastFound.value.length);
                        setReactValue(input, before + '|' + btn.value + after);
                    } else {
                        // No other quality found, append with space
                        setReactValue(input, current ? current + ' ' + btn.value : btn.value);
                    }
                } else {
                    // Non-quality buttons
                    if (current.includes(btn.value)) return;
                    setReactValue(input, current ? current + ' ' + btn.value : btn.value);
                }
            });
        });
    }

    function setupEscapeClear() {
        const input = document.querySelector('#query');
        if (!input) return;
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') setReactValue(input, '');
        });
    }

    const observer = new MutationObserver(() => {
        addFilterButtons();
        setupEscapeClear();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();