Created
May 22, 2025 17:31
-
-
Save intellectronica/83d15d6bc0d2b64b442f574eb7882428 to your computer and use it in GitHub Desktop.
Monkey script for automatically opening Slack in the browser (convenient if you don't use the app)
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
// ==UserScript== | |
// @name slack-auto-open-in-browser | |
// @version 0.4 | |
// @description Automatically redirects to the browser version of Slack using teamUrl from props_node data on ssb/redirect pages. | |
// @author Eleanor Berger (Gemini 2.5 Pro) | |
// @match *://*.slack.com/ssb/redirect* | |
// @grant none | |
// @run-at document-idle | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
// Consistent console log prefix for easier filtering | |
const logPrefix = '[Slack Auto SSB Redirect]'; | |
console.log(`${logPrefix} Script started.`); | |
const propsNode = document.getElementById('props_node'); | |
if (propsNode) { | |
const propsDataString = propsNode.getAttribute('data-props'); | |
if (propsDataString) { | |
try { | |
const props = JSON.parse(propsDataString); | |
// For detailed debugging, you can uncomment the next line to see all parsed props: | |
// console.log(`${logPrefix} Parsed props_node data:`, props); | |
const teamUrl = props.teamUrl; | |
if (teamUrl && typeof teamUrl === 'string' && teamUrl.startsWith('http')) { | |
console.log(`${logPrefix} teamUrl found: "${teamUrl}". Redirecting...`); | |
window.location.href = teamUrl; | |
return; // Exit script after successful redirect | |
} else { | |
console.error(`${logPrefix} Valid teamUrl not found or invalid in props_node data. Value was: "${teamUrl}". Proceeding to fallback.`); | |
attemptClickFallback(); | |
} | |
} catch (e) { | |
console.error(`${logPrefix} Error parsing props_node data. Proceeding to fallback.`, e); | |
attemptClickFallback(); | |
} | |
} else { | |
console.error(`${logPrefix} props_node found but data-props attribute is empty or missing. Proceeding to fallback.`); | |
attemptClickFallback(); | |
} | |
} else { | |
console.warn(`${logPrefix} props_node not found. This might indicate a page structure change. Proceeding to fallback.`); | |
attemptClickFallback(); | |
} | |
function attemptClickFallback() { | |
// This fallback tries to click the link, which might appear dynamically. | |
console.log(`${logPrefix} Fallback: Attempting to find and click the "use Slack in your browser" link.`); | |
const linkSelectorQA = 'a[data-qa="ssb_redirect_open_in_browser"]'; | |
const linkTextContent = "use Slack in your browser"; | |
let linkClicked = false; | |
let attempts = 0; | |
const maxAttempts = 20; // Try for 10 seconds (20 attempts * 500ms interval) | |
const interval = 500; // Milliseconds | |
function findAndClick() { | |
if (linkClicked) { | |
return; // Link has already been found and clicked | |
} | |
attempts++; | |
let targetLink = document.querySelector(linkSelectorQA); | |
if (!targetLink) { | |
// If the data-qa selector fails, try finding by text content. | |
// This is often more robust to minor markup changes. | |
const allLinks = document.querySelectorAll('a'); // Query all anchor tags | |
for (const link of allLinks) { | |
if (link.textContent && link.textContent.trim().toLowerCase() === linkTextContent.toLowerCase()) { | |
// To make this even more specific, you could check for a common class if one exists, | |
// e.g., if (link.classList.contains('c-link') && ...) | |
targetLink = link; | |
console.log(`${logPrefix} Fallback: Found link by text content:`, targetLink); | |
break; | |
} | |
} | |
} | |
if (targetLink) { | |
console.log(`${logPrefix} Fallback: Link found. Clicking...`, targetLink); | |
targetLink.click(); | |
linkClicked = true; | |
} else if (attempts < maxAttempts) { | |
// Optional: More verbose logging for each attempt. | |
// console.log(`${logPrefix} Fallback: Link not found on attempt ${attempts}/${maxAttempts}. Retrying in ${interval}ms.`); | |
setTimeout(findAndClick, interval); | |
} else { | |
console.warn(`${logPrefix} Fallback: Link not found after ${maxAttempts} attempts. The element with text "${linkTextContent}" or selector "${linkSelectorQA}" might not be present, takes too long to appear, or the primary props-based method should have worked.`); | |
} | |
} | |
// Initial call to start polling for the fallback mechanism. | |
// A small initial delay can sometimes help if the element appears very shortly after 'document-idle'. | |
setTimeout(findAndClick, interval); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment