您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Adds quality + ⚡instantRD filter buttons that remember activation and reapply automatically when input changes
当前为
// ==UserScript== // @name DMM Top Filter Buttons // @namespace http://tampermonkey.net/ // @version 1.36 // @description Adds quality + ⚡instantRD filter buttons that remember activation and reapply automatically when input changes // @author Waseem // @match https://debridmediamanager.com/* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; let instantRDActive = false; // persistent state 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: '__bgonly__', class: 'dmm-bgonly' }, { 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 escapeRegex(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function applyInstantRDFilter() { const grid = document.querySelector( '#__next > div > div.mx-1.my-1.grid.grid-cols-1.gap-2.overflow-x-auto.sm\\:grid-cols-2.md\\:grid-cols-3.lg\\:grid-cols-4.xl\\:grid-cols-6' ); if (!grid) return; const cards = grid.querySelectorAll('div.border-2'); cards.forEach(card => { const hasBg = card.classList.contains('bg-gray-800'); card.style.display = instantRDActive ? (hasBg ? '' : 'none') : ''; }); const instantButton = document.querySelector('span.dmm-bgonly'); if (instantButton) { if (instantRDActive) { instantButton.classList.add('active', 'bg-green-800'); } else { instantButton.classList.remove('active', 'bg-green-800'); } } } 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; let lastInserted = null; buttons.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`; if (lastInserted) { container.insertBefore(span, lastInserted.nextSibling); } else { container.insertBefore(span, container.firstChild); } lastInserted = span; span.addEventListener('click', () => { if (btn.value === '__bgonly__') { instantRDActive = !instantRDActive; applyInstantRDFilter(); return; } // Quality buttons if (qualityValues.includes(btn.value)) { let current = input.value.trim(); const clickedQuality = btn.value; const escaped = escapeRegex(clickedQuality); const regex = new RegExp(`(^|\\||\\s)${escaped}($|\\||\\s)`); if (current.match(regex)) { const parts = current.split(' '); const filteredParts = parts.map(part => { const qualityRegex = new RegExp(`(^|\\|)${escaped}($|\\|)`); let cleaned = part.replace(qualityRegex, (match, before, after) => { if (before === '|' && after === '|') return '|'; return ''; }); cleaned = cleaned.replace(/\|{2,}/g, '|').replace(/^\|+|\|+$/g, ''); return cleaned; }).filter(part => part.length > 0); current = filteredParts.join(' ').trim(); setReactValue(input, current); applyInstantRDFilter(); return; } let lastFound = null; qualityValues.forEach(q => { const idx = current.lastIndexOf(q); if (idx !== -1) lastFound = { value: q, index: idx }; }); if (lastFound) { const before = current.slice(0, lastFound.index + lastFound.value.length); const after = current.slice(lastFound.index + lastFound.value.length); current = before + '|' + clickedQuality + after; } else { current = current ? current + ' ' + clickedQuality : clickedQuality; } current = current.replace(/\|{2,}/g, '|').replace(/^\|+|\|+$/g, ''); current = current.replace(/\s+/g, ' ').trim(); setReactValue(input, current); applyInstantRDFilter(); } else { let current = input.value.trim(); if (current.includes(btn.value)) { const regex = new RegExp(`\\s*\\b${escapeRegex(btn.value)}\\b\\s*`, 'g'); current = current.replace(regex, ' ').trim(); current = current.replace(/\s+/g, ' '); setReactValue(input, current); applyInstantRDFilter(); } else { current = current ? current + ' ' + btn.value : btn.value; setReactValue(input, current); applyInstantRDFilter(); } } }); }); // Apply instantRD filter if it was already active applyInstantRDFilter(); } function setupEscapeClear() { const input = document.querySelector('#query'); if (!input) return; document.addEventListener('keydown', (e) => { if (e.key === 'Escape') setReactValue(input, ''); }); // Reapply instantRD filter whenever input changes input.addEventListener('input', () => { applyInstantRDFilter(); }); } const observer = new MutationObserver(() => { addFilterButtons(); setupEscapeClear(); }); observer.observe(document.body, { childList: true, subtree: true }); })();