您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Manage allowed sites dynamically and reference this in other scripts.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/526770/1670381/Site%20Filter%20%28Protocol-Independent%29.js
// ==UserScript== // @name Site Filter (Protocol-Independent) // @namespace http://tampermonkey.net/ // @version 3.0 // @description Manage allowed sites dynamically and reference this in other scripts. // @author blvdmd // @match *://*/* // @noframes // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_download // @run-at document-start // ==/UserScript== (function () { 'use strict'; // Exit if the script is running in an iframe or embedded context if (window.self !== window.top) { return; // Stop execution for embedded pages } const USE_EMOJI_FOR_STATUS = true; // Configurable flag to use emoji for true/false status const SHOW_STATUS_ONLY_IF_TRUE = true; // Configurable flag to show status only if any value is true // ✅ Wait for `SCRIPT_STORAGE_KEY` to be set function waitForScriptStorageKey(maxWait = 1000) { return new Promise(resolve => { const startTime = Date.now(); const interval = setInterval(() => { if (typeof window.SCRIPT_STORAGE_KEY !== 'undefined') { clearInterval(interval); resolve(window.SCRIPT_STORAGE_KEY); } else if (Date.now() - startTime > maxWait) { clearInterval(interval); console.error("🚨 SCRIPT_STORAGE_KEY is not set! Make sure your script sets it **before** @require."); resolve(null); } }, 50); }); } (async function initialize() { async function waitForDocumentReady() { if (document.readyState === "complete") return; return new Promise(resolve => { window.addEventListener("load", resolve, { once: true }); }); } // ✅ Wait for the script storage key const key = await waitForScriptStorageKey(); if (!key) return; // ✅ Ensure the document is fully loaded before setting `shouldRunOnThisSite` await waitForDocumentReady(); const STORAGE_KEY = `additionalSites_${key}`; function getDefaultList() { return typeof window.GET_DEFAULT_LIST === "function" ? window.GET_DEFAULT_LIST() : []; } function normalizeUrl(url) { if (typeof url !== 'string') { url = String(url); } return url.replace(/^https?:\/\//, ''); } let additionalSites = GM_getValue(STORAGE_KEY, []); let mergedSites = buildMergedSites(); // ====== REFACTORED: Deduplicated mergedSites building logic ====== function buildMergedSites() { return [...new Set([...getDefaultList(), ...additionalSites])].map(item => { if (typeof item === 'string') { return { pattern: normalizeUrl(item), preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }; } return { ...item, pattern: normalizeUrl(item.pattern), preProcessingRequired: item.preProcessingRequired || false, postProcessingRequired: item.postProcessingRequired || false, onDemandFloatingButtonRequired: item.onDemandFloatingButtonRequired || false, backgroundChangeObserverRequired: item.backgroundChangeObserverRequired || false }; }); } function refreshMergedSites() { mergedSites = buildMergedSites(); } function wildcardToRegex(pattern) { return new RegExp("^" + pattern .replace(/[-[\]{}()+^$|#\s]/g, '\\$&') .replace(/\./g, '\\.') .replace(/\?/g, '\\?') .replace(/\*/g, '.*') + "$"); } async function shouldRunOnThisSite() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); return mergedSites.some(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)); } // ====== UTILITY: Count wildcard matches for current site ====== function countWildcardMatches() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); return mergedSites.filter(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)).length; } // ====== HTML UI HELPER FUNCTIONS ====== function createModal(title, content, options = {}) { const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; z-index: 999999; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; `; const dialog = document.createElement('div'); dialog.style.cssText = ` background: white; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); max-width: ${options.maxWidth || '600px'}; width: 90%; max-height: 85vh; display: flex; flex-direction: column; overflow: hidden; `; const header = document.createElement('div'); header.style.cssText = ` padding: 20px; border-bottom: 1px solid #e0e0e0; display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; `; const titleEl = document.createElement('h2'); titleEl.textContent = title; titleEl.style.cssText = 'margin: 0; font-size: 20px; font-weight: 600;'; const closeBtn = document.createElement('button'); closeBtn.innerHTML = '✕'; closeBtn.style.cssText = ` background: transparent; border: none; color: white; font-size: 24px; cursor: pointer; padding: 0; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.2s; `; closeBtn.onmouseover = () => closeBtn.style.background = 'rgba(255, 255, 255, 0.2)'; closeBtn.onmouseout = () => closeBtn.style.background = 'transparent'; closeBtn.onclick = () => { document.body.removeChild(modal); if (options.onClose) options.onClose(); }; header.appendChild(titleEl); header.appendChild(closeBtn); const body = document.createElement('div'); body.style.cssText = ` padding: 20px; overflow-y: auto; flex: 1; `; if (typeof content === 'string') { body.innerHTML = content; } else { body.appendChild(content); } dialog.appendChild(header); dialog.appendChild(body); modal.appendChild(dialog); // Close on backdrop click modal.onclick = (e) => { if (e.target === modal) { document.body.removeChild(modal); if (options.onClose) options.onClose(); } }; document.body.appendChild(modal); return { modal, body, closeBtn }; } function createButton(text, onClick, style = 'primary') { const btn = document.createElement('button'); btn.textContent = text; const baseStyle = ` padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s; margin: 5px; `; const styles = { primary: `${baseStyle} background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;`, success: `${baseStyle} background: #10b981; color: white;`, danger: `${baseStyle} background: #ef4444; color: white;`, secondary: `${baseStyle} background: #6b7280; color: white;`, outline: `${baseStyle} background: transparent; color: #667eea; border: 2px solid #667eea;` }; btn.style.cssText = styles[style] || styles.primary; btn.onmouseover = () => btn.style.transform = 'scale(1.05)'; btn.onmouseout = () => btn.style.transform = 'scale(1)'; btn.onclick = onClick; return btn; } function createInput(type, value, placeholder = '') { const input = document.createElement(type === 'textarea' ? 'textarea' : 'input'); if (type !== 'textarea') input.type = type; input.value = value || ''; input.placeholder = placeholder; input.style.cssText = ` width: 100%; padding: 10px; border: 2px solid #e0e0e0; border-radius: 6px; font-size: 14px; font-family: inherit; margin: 5px 0; box-sizing: border-box; transition: border-color 0.2s; `; input.onfocus = () => input.style.borderColor = '#667eea'; input.onblur = () => input.style.borderColor = '#e0e0e0'; return input; } function createCheckbox(label, checked = false) { const container = document.createElement('label'); container.style.cssText = ` display: flex; align-items: center; margin: 10px 0; cursor: pointer; user-select: none; `; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.checked = checked; checkbox.style.cssText = ` width: 20px; height: 20px; margin-right: 10px; cursor: pointer; `; const labelText = document.createElement('span'); labelText.textContent = label; labelText.style.cssText = 'font-size: 14px;'; container.appendChild(checkbox); container.appendChild(labelText); return { container, checkbox }; } function formatStatus(preProcessingRequired, postProcessingRequired, onDemandFloatingButtonRequired, backgroundChangeObserverRequired) { if (SHOW_STATUS_ONLY_IF_TRUE && !preProcessingRequired && !postProcessingRequired && !onDemandFloatingButtonRequired && !backgroundChangeObserverRequired) { return ''; } const preStatus = USE_EMOJI_FOR_STATUS ? (preProcessingRequired ? '✅' : '✖️') : (preProcessingRequired ? 'true' : 'false'); const postStatus = USE_EMOJI_FOR_STATUS ? (postProcessingRequired ? '✅' : '✖️') : (postProcessingRequired ? 'true' : 'false'); const floatingButtonStatus = USE_EMOJI_FOR_STATUS ? (onDemandFloatingButtonRequired ? '✅' : '✖️') : (onDemandFloatingButtonRequired ? 'true' : 'false'); const backgroundObserverStatus = USE_EMOJI_FOR_STATUS ? (backgroundChangeObserverRequired ? '✅' : '✖️') : (backgroundChangeObserverRequired ? 'true' : 'false'); return `Pre: ${preStatus}, Post: ${postStatus}, FB: ${floatingButtonStatus}, BO: ${backgroundObserverStatus}`; } // ====== MENU COMMAND 1: Add Current Site ====== function addCurrentSiteMenu() { const matchCount = countWildcardMatches(); const currentHost = window.top.location.hostname; const currentPath = window.top.location.pathname; const domainParts = currentHost.split('.'); const baseDomain = domainParts.length > 2 ? domainParts.slice(-2).join('.') : domainParts.join('.'); const secondLevelDomain = domainParts.length > 2 ? domainParts.slice(-2, -1)[0] : domainParts[0]; const options = [ { name: `Preferred Domain Match (*${secondLevelDomain}.*)`, pattern: `*${secondLevelDomain}.*` }, { name: `Base Hostname (*.${baseDomain}*)`, pattern: `*.${baseDomain}*` }, { name: `Base Domain (*.${secondLevelDomain}.*)`, pattern: `*.${secondLevelDomain}.*` }, { name: `Host Contains (*${secondLevelDomain}*)`, pattern: `*${secondLevelDomain}*` }, { name: `Exact Path (${currentHost}${currentPath})`, pattern: normalizeUrl(`${window.top.location.href}`) }, { name: "Custom Wildcard Pattern", pattern: normalizeUrl(`${window.top.location.href}`) } ]; const content = document.createElement('div'); const infoBox = document.createElement('div'); infoBox.style.cssText = ` background: #f0f9ff; border: 2px solid #0ea5e9; border-radius: 8px; padding: 15px; margin-bottom: 20px; `; infoBox.innerHTML = ` <div style="font-weight: 600; color: #0c4a6e; margin-bottom: 5px;"> 📊 Current Page Wildcard Matches: ${matchCount} </div> <div style="font-size: 13px; color: #075985;"> This page matches ${matchCount} existing rule${matchCount !== 1 ? 's' : ''} in your include list. </div> `; content.appendChild(infoBox); const sectionTitle = document.createElement('h3'); sectionTitle.textContent = 'Select a pattern to add:'; sectionTitle.style.cssText = 'margin: 20px 0 15px 0; font-size: 16px; color: #333;'; content.appendChild(sectionTitle); let selectedOption = null; const optionButtons = []; options.forEach((opt, index) => { const optBtn = document.createElement('button'); optBtn.textContent = opt.name; optBtn.style.cssText = ` display: block; width: 100%; padding: 12px; margin: 8px 0; border: 2px solid #e0e0e0; border-radius: 8px; background: white; cursor: pointer; text-align: left; font-size: 14px; transition: all 0.2s; `; optBtn.onclick = () => { optionButtons.forEach(btn => { btn.style.borderColor = '#e0e0e0'; btn.style.background = 'white'; }); optBtn.style.borderColor = '#667eea'; optBtn.style.background = '#f5f3ff'; selectedOption = index; }; optionButtons.push(optBtn); content.appendChild(optBtn); }); const patternInput = createInput('text', '', 'Custom pattern (only for Custom Wildcard Pattern)'); patternInput.style.display = 'none'; content.appendChild(patternInput); optionButtons[5].onclick = () => { optionButtons.forEach(btn => { btn.style.borderColor = '#e0e0e0'; btn.style.background = 'white'; }); optionButtons[5].style.borderColor = '#667eea'; optionButtons[5].style.background = '#f5f3ff'; selectedOption = 5; patternInput.style.display = 'block'; patternInput.value = normalizeUrl(`${window.top.location.href}`); }; const configTitle = document.createElement('h3'); configTitle.textContent = 'Configuration Options:'; configTitle.style.cssText = 'margin: 25px 0 15px 0; font-size: 16px; color: #333;'; content.appendChild(configTitle); const preCheck = createCheckbox('Pre-processing Required', false); const postCheck = createCheckbox('Post-processing Required', false); const floatingBtnCheck = createCheckbox('On-demand Floating Button Required', false); const backgroundObsCheck = createCheckbox('Background Change Observer Required', false); content.appendChild(preCheck.container); content.appendChild(postCheck.container); content.appendChild(floatingBtnCheck.container); content.appendChild(backgroundObsCheck.container); const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = 'margin-top: 25px; display: flex; justify-content: flex-end; gap: 10px;'; const { modal } = createModal('➕ Add Current Site to Include List', content, { maxWidth: '650px' }); const cancelBtn = createButton('Cancel', () => { document.body.removeChild(modal); }, 'secondary'); const addBtn = createButton('Add Site', () => { if (selectedOption === null) { alert('⚠️ Please select a pattern option.'); return; } let pattern = normalizeUrl(options[selectedOption].pattern); if (selectedOption === 5) { pattern = normalizeUrl(patternInput.value.trim()); if (!pattern) { alert('⚠️ Invalid pattern. Operation canceled.'); return; } } const entry = { pattern, preProcessingRequired: preCheck.checkbox.checked, postProcessingRequired: postCheck.checkbox.checked, onDemandFloatingButtonRequired: floatingBtnCheck.checkbox.checked, backgroundChangeObserverRequired: backgroundObsCheck.checkbox.checked }; if (!additionalSites.some(item => item.pattern === pattern)) { additionalSites.push(entry); GM_setValue(STORAGE_KEY, additionalSites); refreshMergedSites(); document.body.removeChild(modal); alert(`✅ Added site with pattern: ${pattern}`); } else { alert(`⚠️ Pattern "${pattern}" is already in the list.`); } }, 'success'); buttonContainer.appendChild(cancelBtn); buttonContainer.appendChild(addBtn); content.appendChild(buttonContainer); } // ====== MENU COMMAND 2: Advanced Management ====== function showAdvancedManagement() { const content = document.createElement('div'); const stats = document.createElement('div'); stats.style.cssText = ` background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 8px; margin-bottom: 20px; text-align: center; `; stats.innerHTML = ` <div style="font-size: 32px; font-weight: 700;">${additionalSites.length}</div> <div style="font-size: 14px; opacity: 0.9;">User-Defined Sites</div> `; content.appendChild(stats); const buttonBar = document.createElement('div'); buttonBar.style.cssText = ` display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 20px; justify-content: center; `; const refreshList = () => { document.body.querySelectorAll('[data-modal-advanced]').forEach(m => document.body.removeChild(m)); showAdvancedManagement(); }; buttonBar.appendChild(createButton('📤 Export', exportAdditionalSites, 'primary')); buttonBar.appendChild(createButton('📥 Import', () => { importAdditionalSites(refreshList); }, 'primary')); buttonBar.appendChild(createButton('🗑️ Clear All', () => { clearAllEntriesConfirm(refreshList); }, 'danger')); content.appendChild(buttonBar); const listTitle = document.createElement('h3'); listTitle.textContent = 'Included Sites:'; listTitle.style.cssText = 'margin: 20px 0 15px 0; font-size: 16px; color: #333;'; content.appendChild(listTitle); if (additionalSites.length === 0) { const emptyMsg = document.createElement('div'); emptyMsg.style.cssText = ` text-align: center; padding: 40px; color: #9ca3af; font-size: 16px; `; emptyMsg.textContent = 'No user-defined sites added yet.'; content.appendChild(emptyMsg); } else { const listContainer = document.createElement('div'); listContainer.style.cssText = ` max-height: 400px; overflow-y: auto; border: 1px solid #e0e0e0; border-radius: 8px; `; additionalSites.forEach((item, index) => { const siteCard = document.createElement('div'); siteCard.style.cssText = ` padding: 15px; border-bottom: 1px solid #e0e0e0; transition: background 0.2s; `; siteCard.onmouseover = () => siteCard.style.background = '#f9fafb'; siteCard.onmouseout = () => siteCard.style.background = 'white'; const patternDiv = document.createElement('div'); patternDiv.style.cssText = ` font-weight: 600; color: #1f2937; margin-bottom: 8px; word-break: break-all; `; patternDiv.textContent = item.pattern; const statusDiv = document.createElement('div'); statusDiv.style.cssText = 'font-size: 12px; color: #6b7280; margin-bottom: 10px;'; const status = formatStatus(item.preProcessingRequired, item.postProcessingRequired, item.onDemandFloatingButtonRequired, item.backgroundChangeObserverRequired); statusDiv.textContent = status || 'No special processing'; const actionBar = document.createElement('div'); actionBar.style.cssText = 'display: flex; gap: 8px;'; const editBtn = createButton('✏️ Edit', () => { editEntryDialog(index, refreshList); }, 'outline'); editBtn.style.padding = '6px 12px'; editBtn.style.fontSize = '12px'; const deleteBtn = createButton('🗑️ Delete', () => { deleteEntryConfirm(index, refreshList); }, 'danger'); deleteBtn.style.padding = '6px 12px'; deleteBtn.style.fontSize = '12px'; actionBar.appendChild(editBtn); actionBar.appendChild(deleteBtn); siteCard.appendChild(patternDiv); siteCard.appendChild(statusDiv); siteCard.appendChild(actionBar); listContainer.appendChild(siteCard); }); content.appendChild(listContainer); } const { modal } = createModal('⚙️ IncludeSites-Advanced (View/Edit/Delete/Import/Export)', content, { maxWidth: '750px' }); modal.setAttribute('data-modal-advanced', 'true'); } function editEntryDialog(index, onComplete) { const entry = additionalSites[index]; const content = document.createElement('div'); const label1 = document.createElement('label'); label1.textContent = 'Pattern:'; label1.style.cssText = 'display: block; margin-top: 15px; margin-bottom: 5px; font-weight: 600; color: #374151;'; content.appendChild(label1); const patternInput = createInput('text', entry.pattern, 'Enter pattern'); content.appendChild(patternInput); const configTitle = document.createElement('h3'); configTitle.textContent = 'Configuration Options:'; configTitle.style.cssText = 'margin: 25px 0 15px 0; font-size: 16px; color: #333;'; content.appendChild(configTitle); const preCheck = createCheckbox('Pre-processing Required', entry.preProcessingRequired); const postCheck = createCheckbox('Post-processing Required', entry.postProcessingRequired); const floatingBtnCheck = createCheckbox('On-demand Floating Button Required', entry.onDemandFloatingButtonRequired); const backgroundObsCheck = createCheckbox('Background Change Observer Required', entry.backgroundChangeObserverRequired); content.appendChild(preCheck.container); content.appendChild(postCheck.container); content.appendChild(floatingBtnCheck.container); content.appendChild(backgroundObsCheck.container); const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = 'margin-top: 25px; display: flex; justify-content: flex-end; gap: 10px;'; const { modal } = createModal('✏️ Edit Entry', content, { maxWidth: '600px' }); const cancelBtn = createButton('Cancel', () => { document.body.removeChild(modal); }, 'secondary'); const saveBtn = createButton('Save Changes', () => { const newPattern = normalizeUrl(patternInput.value.trim()); if (!newPattern) { alert('⚠️ Invalid pattern. Operation canceled.'); return; } entry.pattern = newPattern; entry.preProcessingRequired = preCheck.checkbox.checked; entry.postProcessingRequired = postCheck.checkbox.checked; entry.onDemandFloatingButtonRequired = floatingBtnCheck.checkbox.checked; entry.backgroundChangeObserverRequired = backgroundObsCheck.checkbox.checked; GM_setValue(STORAGE_KEY, additionalSites); refreshMergedSites(); document.body.removeChild(modal); alert('✅ Entry updated successfully.'); if (onComplete) onComplete(); }, 'success'); buttonContainer.appendChild(cancelBtn); buttonContainer.appendChild(saveBtn); content.appendChild(buttonContainer); } function deleteEntryConfirm(index, onComplete) { const entry = additionalSites[index]; if (confirm(`🗑️ Are you sure you want to delete this entry?\n\nPattern: ${entry.pattern}`)) { additionalSites.splice(index, 1); GM_setValue(STORAGE_KEY, additionalSites); refreshMergedSites(); alert('✅ Entry deleted successfully.'); if (onComplete) onComplete(); } } function clearAllEntriesConfirm(onComplete) { if (additionalSites.length === 0) { alert('⚠️ No user-defined entries to clear.'); return; } if (confirm(`🚨 You have ${additionalSites.length} entries. Clear all?`)) { additionalSites = []; GM_setValue(STORAGE_KEY, additionalSites); refreshMergedSites(); alert('✅ All user-defined entries cleared.'); if (onComplete) onComplete(); } } function exportAdditionalSites() { const data = JSON.stringify(additionalSites, null, 2); const blob = new Blob([data], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'additionalSites_backup.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); alert('📤 Additional sites exported as JSON.'); } function importAdditionalSites(onComplete) { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.style.display = 'none'; input.onchange = event => { const reader = new FileReader(); reader.onload = e => { try { const importedData = JSON.parse(e.target.result); if (Array.isArray(importedData)) { additionalSites = importedData.map(item => { if (typeof item === 'string') { return { pattern: normalizeUrl(item), preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }; } else if (typeof item === 'object' && item.pattern) { return { pattern: normalizeUrl(item.pattern), preProcessingRequired: item.preProcessingRequired || false, postProcessingRequired: item.postProcessingRequired || false, onDemandFloatingButtonRequired: item.onDemandFloatingButtonRequired || false, backgroundChangeObserverRequired: item.backgroundChangeObserverRequired || false }; } throw new Error('Invalid data format'); }); GM_setValue(STORAGE_KEY, additionalSites); refreshMergedSites(); alert('📥 Sites imported successfully.'); if (onComplete) onComplete(); } else { throw new Error('Invalid data format'); } } catch (error) { alert('❌ Failed to import sites: ' + error.message); } }; reader.readAsText(event.target.files[0]); }; document.body.appendChild(input); input.click(); document.body.removeChild(input); } // ====== REGISTER MENU COMMANDS (Simplified to 2) ====== GM_registerMenuCommand(`➕ Add Current Site to Include List (Included via ${countWildcardMatches()} wildcard matches)`, addCurrentSiteMenu); GM_registerMenuCommand("⚙️ IncludeSites-Advanced (View/Edit/Delete/Import/Export)", showAdvancedManagement); // ====== EXPOSE PUBLIC API ====== window.shouldRunOnThisSite = shouldRunOnThisSite; window.isPreProcessingRequired = function() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); const entry = mergedSites.find(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)); return entry ? entry.preProcessingRequired : false; }; window.isPostProcessingRequired = function() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); const entry = mergedSites.find(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)); return entry ? entry.postProcessingRequired : false; }; window.isOnDemandFloatingButtonRequired = function() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); const entry = mergedSites.find(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)); return entry ? entry.onDemandFloatingButtonRequired : false; }; window.isBackgroundChangeObserverRequired = function() { const currentFullPath = normalizeUrl(`${window.top.location.href}`); const entry = mergedSites.find(item => wildcardToRegex(normalizeUrl(item.pattern)).test(currentFullPath)); return entry ? entry.backgroundChangeObserverRequired : false; }; })(); })(); //To use this in another script use @require // // @run-at document-end // // ==/UserScript== // window.SCRIPT_STORAGE_KEY = "magnetLinkHashChecker"; // UNIQUE STORAGE KEY // window.GET_DEFAULT_LIST = function() { // return [ // { pattern: "*1337x.*", preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }, // { pattern: "*yts.*", preProcessingRequired: true, postProcessingRequired: true, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }, // { pattern: "*torrentgalaxy.*", preProcessingRequired: false, postProcessingRequired: true, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }, // { pattern: "*bitsearch.*", preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }, // { pattern: "*thepiratebay.*", preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false }, // { pattern: "*ext.*", preProcessingRequired: false, postProcessingRequired: false, onDemandFloatingButtonRequired: false, backgroundChangeObserverRequired: false } // ]; // }; // (async function () { // 'use strict'; // // ✅ Wait until `shouldRunOnThisSite` is available // while (typeof shouldRunOnThisSite === 'undefined') { // await new Promise(resolve => setTimeout(resolve, 50)); // } // if (!(await shouldRunOnThisSite())) return; // //alert("running"); // console.log("Pre-Customization enabled for this site: " + isPreProcessingRequired() ); // console.log("Post-Customization enabled for this site: " + isPostProcessingRequired() ); // const OFFCLOUD_CACHE_API_URL = 'https://offcloud.com/api/cache';