Greasy Fork is available in English.

Site Filter (Protocol-Independent)

Manage allowed sites dynamically and reference this in other scripts.

נכון ליום 13-02-2025. ראה הגרסה האחרונה.

אין להתקין סקריפט זה ישירות. זוהי ספריה עבור סקריפטים אחרים // @require https://update.greatest.deepsurf.us/scripts/526770/1536567/Site%20Filter%20%28Protocol-Independent%29.js

  1. // ==UserScript==
  2. // @name Site Filter (Protocol-Independent)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Manage allowed sites dynamically and reference this in other scripts.
  6. // @author You
  7. // @match *://*/*
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_registerMenuCommand
  11. // @grant GM_download
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. const STORAGE_KEY = "additionalSites";
  18.  
  19. function getDefaultList() {
  20. return [
  21. "*.example.*",
  22. "*example2*"
  23. ];
  24. }
  25.  
  26. function normalizeUrl(url) {
  27. return url.replace(/^https?:\/\//, ''); // Remove "http://" or "https://"
  28. }
  29.  
  30. let additionalSites = GM_getValue(STORAGE_KEY, []);
  31. let mergedSites = [...new Set([...getDefaultList(), ...additionalSites])].map(normalizeUrl);
  32.  
  33. GM_registerMenuCommand("➕ Add Current Site to Include List", addCurrentSiteMenu);
  34. GM_registerMenuCommand("📜 View Included Sites", viewIncludedSites);
  35. GM_registerMenuCommand("🗑️ Delete Specific Entries", deleteEntries);
  36. GM_registerMenuCommand("✏️ Edit an Entry", editEntry);
  37. GM_registerMenuCommand("🚨 Clear All Entries", clearAllEntries);
  38. GM_registerMenuCommand("📤 Export Site List as JSON", exportAdditionalSites);
  39. GM_registerMenuCommand("📥 Import Site List from JSON", importAdditionalSites);
  40.  
  41. async function shouldRunOnThisSite() {
  42. const currentFullPath = normalizeUrl(`${window.location.href}`);
  43. return mergedSites.some(pattern => wildcardToRegex(normalizeUrl(pattern)).test(currentFullPath));
  44. }
  45.  
  46. // function wildcardToRegex(pattern) {
  47. // return new RegExp("^" + pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.') + "$");
  48. // }
  49.  
  50. /**
  51. * Convert a wildcard pattern (e.g., "*.example.com/index.php?/forums/*") into a valid regex.
  52. * - `*` → Matches any characters (`.*`)
  53. * - `?` → Treated as a **literal question mark** (`\?`)
  54. * - `.` → Treated as a **literal dot** (`\.`)
  55. */
  56. function wildcardToRegex(pattern) {
  57. return new RegExp("^" + pattern
  58. .replace(/[-[\]{}()+^$|#\s]/g, '\\$&') // Escape regex special characters (EXCEPT `.` and `?`)
  59. .replace(/\./g, '\\.') // Ensure `.` is treated as a literal dot
  60. .replace(/\?/g, '\\?') // Ensure `?` is treated as a literal question mark
  61. .replace(/\*/g, '.*') // Convert `*` to `.*` (match any sequence)
  62. + "$");
  63. }
  64.  
  65.  
  66. function addCurrentSiteMenu() {
  67. const currentHost = window.location.hostname;
  68. const currentPath = window.location.pathname;
  69. const domainParts = currentHost.split('.');
  70. const baseDomain = domainParts.length > 2 ? domainParts.slice(-2).join('.') : domainParts.join('.');
  71. const secondLevelDomain = domainParts.length > 2 ? domainParts.slice(-2, -1)[0] : domainParts[0];
  72.  
  73. const options = [
  74. { name: `Base Hostname (*.${baseDomain})`, pattern: `*.${baseDomain}` },
  75. { name: `Base Domain (*.${secondLevelDomain}.*)`, pattern: `*.${secondLevelDomain}.*` },
  76. { name: `Host Contains (*${secondLevelDomain}*)`, pattern: `*${secondLevelDomain}*` },
  77. { name: `Exact Path (${currentHost}${currentPath})`, pattern: normalizeUrl(`${window.location.href}`) },
  78. { name: "Custom Wildcard Pattern", pattern: normalizeUrl(`${window.location.href}`) }
  79. ];
  80.  
  81. const userChoice = prompt(
  82. "Select an option to add the site:\n" +
  83. options.map((opt, index) => `${index + 1}. ${opt.name}`).join("\n") +
  84. "\nEnter a number or cancel."
  85. );
  86.  
  87. if (!userChoice) return;
  88. const selectedIndex = parseInt(userChoice, 10) - 1;
  89. if (selectedIndex >= 0 && selectedIndex < options.length) {
  90. let pattern = normalizeUrl(options[selectedIndex].pattern);
  91. if (options[selectedIndex].name === "Custom Wildcard Pattern") {
  92. pattern = normalizeUrl(prompt("Edit custom wildcard pattern:", pattern));
  93. if (!pattern.trim()) return alert("Invalid pattern. Operation canceled.");
  94. }
  95. if (!additionalSites.includes(pattern)) {
  96. additionalSites.push(pattern);
  97. GM_setValue(STORAGE_KEY, additionalSites);
  98. mergedSites = [...new Set([...getDefaultList(), ...additionalSites])].map(normalizeUrl);
  99. alert(`✅ Added site with pattern: ${pattern}`);
  100. }
  101. }
  102. }
  103.  
  104. function viewIncludedSites() {
  105. //alert(`🔍 Included Sites:\n${mergedSites.join("\n") || "No sites added yet."}`);
  106. alert(`🔍 Included Sites:\n${additionalSites.join("\n") || "No sites added yet."}`);
  107. }
  108.  
  109. function deleteEntries() {
  110. if (additionalSites.length === 0) return alert("⚠️ No user-defined entries to delete.");
  111. const userChoice = prompt("Select entries to delete (comma-separated numbers):\n" +
  112. additionalSites.map((item, index) => `${index + 1}. ${item}`).join("\n"));
  113. if (!userChoice) return;
  114. const indicesToRemove = userChoice.split(',').map(num => parseInt(num.trim(), 10) - 1);
  115. additionalSites = additionalSites.filter((_, index) => !indicesToRemove.includes(index));
  116. GM_setValue(STORAGE_KEY, additionalSites);
  117. mergedSites = [...new Set([...getDefaultList(), ...additionalSites])].map(normalizeUrl);
  118. alert("✅ Selected entries have been deleted.");
  119. }
  120.  
  121. function editEntry() {
  122. if (additionalSites.length === 0) return alert("⚠️ No user-defined entries to edit.");
  123. const userChoice = prompt("Select an entry to edit:\n" +
  124. additionalSites.map((item, index) => `${index + 1}. ${item}`).join("\n"));
  125. if (!userChoice) return;
  126. const selectedIndex = parseInt(userChoice, 10) - 1;
  127. if (selectedIndex < 0 || selectedIndex >= additionalSites.length) return alert("❌ Invalid selection.");
  128. const newPattern = normalizeUrl(prompt("Edit the pattern:", additionalSites[selectedIndex]));
  129. if (newPattern && newPattern.trim() && newPattern !== additionalSites[selectedIndex]) {
  130. additionalSites[selectedIndex] = newPattern.trim();
  131. GM_setValue(STORAGE_KEY, additionalSites);
  132. mergedSites = [...new Set([...getDefaultList(), ...additionalSites])].map(normalizeUrl);
  133. alert("✅ Entry updated.");
  134. }
  135. }
  136.  
  137. function clearAllEntries() {
  138. if (additionalSites.length === 0) return alert("⚠️ No user-defined entries to clear.");
  139. if (confirm(`🚨 You have ${additionalSites.length} entries. Clear all?`)) {
  140. additionalSites = [];
  141. GM_setValue(STORAGE_KEY, additionalSites);
  142. mergedSites = [...getDefaultList()].map(normalizeUrl);
  143. alert("✅ All user-defined entries cleared.");
  144. }
  145. }
  146.  
  147. function exportAdditionalSites() {
  148. GM_download("data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(additionalSites, null, 2)), "additionalSites_backup.json");
  149. alert("📤 Additional sites exported as JSON.");
  150. }
  151.  
  152. function importAdditionalSites() {
  153. const input = document.createElement("input");
  154. input.type = "file";
  155. input.accept = ".json";
  156. input.onchange = event => {
  157. const reader = new FileReader();
  158. reader.onload = e => {
  159. additionalSites = JSON.parse(e.target.result);
  160. GM_setValue(STORAGE_KEY, additionalSites);
  161. mergedSites = [...new Set([...getDefaultList(), ...additionalSites])].map(normalizeUrl);
  162. alert("📥 Sites imported successfully.");
  163. };
  164. reader.readAsText(event.target.files[0]);
  165. };
  166. input.click();
  167. }
  168.  
  169. window.shouldRunOnThisSite = shouldRunOnThisSite;
  170. })();