Last active
June 17, 2025 13:01
-
-
Save ajorpheus/047bef282505e35e5881acec9fafca09 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Following grants are needed for some of the functions below to function | |
| // @grant GM_openInTab | |
| // @grant GM_xmlhttpRequest | |
| // @grant GM_notification | |
| // Default configuration object that can be overridden | |
| window.TM_CONFIG = window.TM_CONFIG || { | |
| debug: true, | |
| notificationTimeout: 3000, | |
| clickMethods: { | |
| standardClick: true, // Method 1: element.click() | |
| jQueryClick: true, // Method 2: $(element).click() | |
| mouseEvents: false, // Method 3: Simulate mousedown/mouseup/click events | |
| directNavigation: false // Method 4: Navigate directly to href | |
| } | |
| }; | |
| function log_noti_simple(text, timeout = 2000) { | |
| console.log(`Running "${GM_info.script.name}"`) | |
| // Timeout should be at least 1 second (1000ms) for it to be useful | |
| timeout = timeout < 1000 ? 1000 : timeout; | |
| GM_notification({ | |
| title: `${GM_info.script.name}`, | |
| text: text, | |
| timeout: timeout, | |
| onclick: () => { | |
| console.log("My notice was clicked."); | |
| window.focus(); | |
| } | |
| }) | |
| } | |
| // Enhanced logging function with notification support | |
| function log(message, showNotification = false) { | |
| const timestamp = new Date().toLocaleTimeString(); | |
| const formattedMessage = `[${GM_info.script.name} ${timestamp}] ${message}`; | |
| // Always log to console | |
| console.log(formattedMessage); | |
| // Show notification if enabled and requested | |
| if (window.TM_CONFIG.debug && showNotification) { | |
| GM_notification({ | |
| title: GM_info.script.name, | |
| text: message, | |
| timeout: window.TM_CONFIG.notificationTimeout | |
| }); | |
| } | |
| } | |
| // Safely get element text content | |
| function safeGetText(element) { | |
| if (!element) return ''; | |
| return element.textContent || element.innerText || ''; | |
| } | |
| // Safely get element attribute | |
| function safeGetAttribute(element, attr) { | |
| if (!element || typeof element.getAttribute !== 'function') return ''; | |
| return element.getAttribute(attr) || ''; | |
| } | |
| // Advanced click function with multiple methods | |
| function advancedClick(element) { | |
| if (!element) { | |
| log('Cannot click: Element is null or undefined', true); | |
| return; | |
| } | |
| log('Attempting configured click methods on the element...', false); | |
| // Method 1: Standard click() | |
| if (window.TM_CONFIG.clickMethods.standardClick) { | |
| try { | |
| element.click(); | |
| log('Method 1: Standard click() called', true); | |
| } catch (e) { | |
| log(`Method 1 failed: ${e.message}`, false); | |
| } | |
| } else { | |
| log('Method 1: Standard click() SKIPPED (disabled in config)', false); | |
| } | |
| // Method 2: jQuery click (if jQuery exists) | |
| if (window.TM_CONFIG.clickMethods.jQueryClick) { | |
| try { | |
| if (typeof $ !== 'undefined') { | |
| $(element).click(); | |
| log('Method 2: jQuery click() called', true); | |
| } else { | |
| log('Method 2: jQuery not available', false); | |
| } | |
| } catch (e) { | |
| log(`Method 2 failed: ${e.message}`, false); | |
| } | |
| } else { | |
| log('Method 2: jQuery click() SKIPPED (disabled in config)', false); | |
| } | |
| // Method 3: Trigger mousedown + mouseup + click events | |
| if (window.TM_CONFIG.clickMethods.mouseEvents) { | |
| try { | |
| ['mousedown', 'mouseup', 'click'].forEach(eventType => { | |
| const event = new MouseEvent(eventType, { | |
| view: window, | |
| bubbles: true, | |
| cancelable: true, | |
| buttons: 1 | |
| }); | |
| element.dispatchEvent(event); | |
| }); | |
| log('Method 3: MouseEvents dispatched', true); | |
| } catch (e) { | |
| log(`Method 3 failed: ${e.message}`, false); | |
| } | |
| } else { | |
| log('Method 3: MouseEvents SKIPPED (disabled in config)', false); | |
| } | |
| // Method 4: Navigate directly to the href | |
| if (window.TM_CONFIG.clickMethods.directNavigation) { | |
| try { | |
| const href = safeGetAttribute(element, 'href'); | |
| if (href) { | |
| log(`Method 4: Navigating directly to ${href}`, true); | |
| window.location.href = href; | |
| } else { | |
| log('Method 4: No href attribute found', false); | |
| } | |
| } catch (e) { | |
| log(`Method 4 failed: ${e.message}`, false); | |
| } | |
| } else { | |
| log('Method 4: Direct navigation SKIPPED (disabled in config)', false); | |
| } | |
| log('All configured click methods attempted', true); | |
| } | |
| function processJSON_Response(response) { | |
| console.log('Received response'); | |
| console.log([ | |
| response.status, | |
| response.statusText, | |
| response.readyState, | |
| response.responseHeaders, | |
| response.responseText, | |
| response.finalUrl | |
| ].join("\n")); | |
| } | |
| function reportAJAX_Error(rspObj) { | |
| console.error(`TM scrpt => Error ${rspObj.status}! ${rspObj.statusText}`); | |
| } | |
| function callMacro(jNode, macroLocation, callback = null) { | |
| console.log("Calling macro for " + window.location + " for jNode " + jNode) | |
| curl(macroLocation, callback); | |
| } | |
| function curl(apiURL, callback = null) { | |
| GM_xmlhttpRequest({ | |
| method: "GET", | |
| url: apiURL, | |
| responseType: "text", | |
| onload: (response) => { | |
| processJSON_Response(response); | |
| if (callback) { | |
| console.log('Inside callback'); | |
| callback(); | |
| } | |
| }, | |
| onabort: reportAJAX_Error, | |
| onerror: reportAJAX_Error, | |
| ontimeout: reportAJAX_Error | |
| }); | |
| } | |
| function closeTab() { | |
| log("Closing tab now..."); | |
| window.close(); | |
| } | |
| function clickIt(jNode) { | |
| //alert("I am going to click it"); | |
| jNode.click() | |
| } | |
| function hrefClick(jNode) { | |
| //alert("I am going to click it"); | |
| window.location = jNode.attr('href') | |
| } | |
| // Function to process and click on an element with detailed logging | |
| function processAndClickElement(jqElement, description = "element") { | |
| try { | |
| // Convert jQuery element to DOM element if needed | |
| const element = jqElement instanceof jQuery ? jqElement[0] : jqElement; | |
| if (!element) { | |
| log('Error: Element is null or undefined', true); | |
| return false; | |
| } | |
| log(`Found ${description}`, false); | |
| // Get element details for debugging | |
| const elementDetails = { | |
| text: safeGetText(element).trim(), | |
| href: element.tagName && element.tagName.toLowerCase() === 'a' ? (safeGetAttribute(element, 'href') || 'none') : 'n/a', | |
| id: element.id || 'none', | |
| classes: element.className || 'none', | |
| tagName: element.tagName || 'unknown' | |
| }; | |
| log(`${description} details: ${JSON.stringify(elementDetails)}`, false); | |
| // Small delay before clicking | |
| setTimeout(() => { | |
| advancedClick(element); | |
| }, 500); | |
| return true; | |
| } catch (error) { | |
| log(`Error processing ${description}: ${error.message}`, true); | |
| return false; | |
| } | |
| } | |
| function getRemoteTriggerMacroUrl(macroUUID, compUUID, ...args) { | |
| var argValue = Array.prototype.join.call(args, ','); | |
| return `https://trigger.keyboardmaestro.com/t/${compUUID}/${macroUUID}?${argValue}`; | |
| } | |
| function getPublicWebMacroUrl(uuid, ...args) { | |
| var argValue = Array.prototype.join.call(args, ','); | |
| console.log(`********** argValue: ${argValue} `); | |
| return `https://localhost:4491/action.html?macro=${uuid}&value=${argValue}`; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment