random bun scripts that dont fit anywhere else
at main 6.5 kB view raw
1// ==UserScript== 2// @name Slack Allow HTTP OAuth urls 3// @namespace https://tangled.sh/@dunkirk.sh/bunplayground/slack-http-allowed 4// @version 0.1 5// @description 6// @author Kieran Klukas 7// @match https://api.slack.com/apps/*/oauth* 8// @grant none 9// @run-at document-end 10// ==/UserScript== 11 12(() => { 13 // Track HTTP inputs to avoid redundant processing 14 const httpInputs = new Set(); 15 16 // Add CSS to style the editor table layout 17 function addCustomStyles() { 18 const styleEl = document.createElement("style"); 19 styleEl.textContent = ` 20 .p-url_table_editor__actions { 21 width: 176px !important; 22 } 23 .p-url_table_editor__fields { 24 width: calc(100% - 176px) !important; 25 } 26 `; 27 document.head.appendChild(styleEl); 28 } 29 30 function watchForHTTPEntries() { 31 const urlInputs = document.querySelectorAll( 32 "[data-url-table-editor-input]", 33 ); 34 35 // Add event listeners to each input field that doesn't already have one 36 for (const input of urlInputs) { 37 if (input.hasHttpListener) continue; 38 39 input.hasHttpListener = true; 40 input.addEventListener("input", function () { 41 const row = this.closest("[data-row]"); 42 if (!row) return; 43 44 const saveButton = row.querySelector( 45 '[data-js-url-editor="save-create"]', 46 ); 47 if (!saveButton) return; 48 49 // Check if input contains http:// (non-https URL) 50 if (this.value.trim().startsWith("http://")) { 51 // Make the button sassy and green 52 saveButton.classList.remove("disabled"); 53 saveButton.removeAttribute("disabled"); 54 saveButton.textContent = "add 😈"; 55 56 // Add to tracking set 57 httpInputs.add(this); 58 } else { 59 // Reset to default state if not http:// 60 saveButton.textContent = "Add"; 61 62 // Remove from tracking set 63 httpInputs.delete(this); 64 65 // Only re-disable if empty (assuming that's the original logic) 66 if (!this.value.trim()) { 67 saveButton.classList.add("disabled"); 68 saveButton.setAttribute("disabled", ""); 69 } 70 } 71 }); 72 } 73 } 74 75 // Function to specifically fix HTTP buttons that might have been disabled 76 function fixHttpButtons() { 77 // Only process inputs we know have HTTP URLs 78 for (const input of httpInputs) { 79 if (!input.value.trim().startsWith("http://")) { 80 httpInputs.delete(input); 81 continue; 82 } 83 84 const row = input.closest("[data-row]"); 85 if (!row) { 86 httpInputs.delete(input); 87 continue; 88 } 89 90 const saveButton = row.querySelector( 91 '[data-js-url-editor="save-create"]', 92 ); 93 if (!saveButton) { 94 httpInputs.delete(input); 95 continue; 96 } 97 98 // Force the button to stay enabled 99 saveButton.classList.remove("disabled"); 100 saveButton.removeAttribute("disabled"); 101 saveButton.textContent = "add 😈"; 102 } 103 } 104 105 // Watch for attribute changes on buttons to detect when they're disabled again 106 function watchButtonAttributes() { 107 const buttonObserver = new window.MutationObserver((mutations) => { 108 for (const mutation of mutations) { 109 if ( 110 mutation.type === "attributes" && 111 (mutation.attributeName === "disabled" || 112 mutation.attributeName === "class") 113 ) { 114 const button = mutation.target; 115 const row = button.closest("[data-row]"); 116 if (!row) continue; 117 118 const input = row.querySelector("[data-url-table-editor-input]"); 119 if (!input || !input.value.trim().startsWith("http://")) continue; 120 121 // This is an HTTP input with a button that was just disabled 122 // Re-enable it immediately 123 if ( 124 button.classList.contains("disabled") || 125 button.hasAttribute("disabled") 126 ) { 127 button.classList.remove("disabled"); 128 button.removeAttribute("disabled"); 129 button.textContent = "add 😈"; 130 } 131 } 132 } 133 }); 134 135 // Observe all save buttons for attribute changes 136 const saveButtons = document.querySelectorAll( 137 '[data-js-url-editor="save-create"]', 138 ); 139 for (const button of saveButtons) { 140 buttonObserver.observe(button, { attributes: true }); 141 } 142 143 return buttonObserver; 144 } 145 146 // Run the CSS additions immediately 147 addCustomStyles(); 148 149 // Run the function immediately 150 watchForHTTPEntries(); 151 fixHttpButtons(); 152 const buttonObserver = watchButtonAttributes(); 153 154 // Then run it again after a delay to ensure DOM is fully loaded 155 setTimeout(() => { 156 watchForHTTPEntries(); 157 fixHttpButtons(); 158 }, 1000); 159 160 // Run the button fix less frequently to reduce browser lag 161 setInterval(fixHttpButtons, 1000); 162 163 // Observer for new inputs 164 const inputObserver = new window.MutationObserver((mutations) => { 165 // Throttle the observer callback 166 if (inputObserver.isProcessing) return; 167 inputObserver.isProcessing = true; 168 169 setTimeout(() => { 170 let hasNewInputs = false; 171 let hasNewButtons = false; 172 173 for (const mutation of mutations) { 174 if (mutation.addedNodes.length) { 175 hasNewInputs = true; 176 177 // Check if any new save buttons were added 178 for (const node of mutation.addedNodes) { 179 if (node.nodeType === 1) { 180 // Node.ELEMENT_NODE is 1 181 const newButtons = node.querySelectorAll 182 ? node.querySelectorAll('[data-js-url-editor="save-create"]') 183 : []; 184 if (newButtons.length > 0) hasNewButtons = true; 185 } 186 } 187 } 188 } 189 190 if (hasNewInputs) { 191 watchForHTTPEntries(); 192 } 193 194 if (hasNewButtons) { 195 // Observe any new buttons 196 const newSaveButtons = document.querySelectorAll( 197 '[data-js-url-editor="save-create"]', 198 ); 199 for (const button of newSaveButtons) { 200 if (!button.hasAttributeObserver) { 201 buttonObserver.observe(button, { attributes: true }); 202 button.hasAttributeObserver = true; 203 } 204 } 205 } 206 207 fixHttpButtons(); 208 inputObserver.isProcessing = false; 209 }, 200); 210 }); 211 212 // Start observing the document with fewer things to watch 213 inputObserver.observe(document.body, { 214 childList: true, 215 subtree: true, 216 }); 217})();