Forked from lancethomps/close_notifications_applescript.js
Created
March 6, 2023 19:06
-
-
Save arielazem/7f8b18e5f7ea32ed7d7eac22e3e6e6b9 to your computer and use it in GitHub Desktop.
Revisions
-
lancethomps revised this gist
Jan 7, 2023 . No changes.There are no files selected for viewing
-
lancethomps revised this gist
Jan 6, 2023 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -43,6 +43,7 @@ function run(input, parameters) { }; const V11_OR_GREATER = isBigSurOrGreater(); const V12 = systemVersion()[0] === 12; const APP_NAME_MATCHER_ROLE = V11_OR_GREATER ? "AXStaticText" : "AXImage"; const hasAppNames = notNullOrEmpty(appNames); const hasSkipAppNames = notNullOrEmpty(skipAppNames); @@ -104,7 +105,10 @@ function run(input, parameters) { if (!V11_OR_GREATER) { return notificationCenter.windows(); } if (V12) { return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements(); } return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements[0].uiElements(); } catch (err) { logError("Could not get NotificationCenter groups"); if (retryOnError) { -
lancethomps revised this gist
Mar 2, 2022 . 1 changed file with 58 additions and 27 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,7 @@ function run(input, parameters) { const appNames = []; const skipAppNames = []; const verbose = true; const scriptName = "close_notifications_applescript"; @@ -11,69 +12,79 @@ function run(input, parameters) { const notNull = (val) => { return val !== null && val !== undefined; }; const isNull = (val) => { return !notNull(val); }; const notNullOrEmpty = (val) => { return notNull(val) && val.length > 0; }; const isNullOrEmpty = (val) => { return !notNullOrEmpty(val); }; const isError = (maybeErr) => { return notNull(maybeErr) && (maybeErr instanceof Error || maybeErr.message); }; const systemVersion = () => { return Application("Finder").version().split(".").map(val => parseInt(val)); }; const systemVersionGreaterThanOrEqualTo = (vers) => { return systemVersion()[0] >= vers; }; const isBigSurOrGreater = () => { return systemVersionGreaterThanOrEqualTo(11); }; const V11_OR_GREATER = isBigSurOrGreater(); const APP_NAME_MATCHER_ROLE = V11_OR_GREATER ? "AXStaticText" : "AXImage"; const hasAppNames = notNullOrEmpty(appNames); const hasSkipAppNames = notNullOrEmpty(skipAppNames); const hasAppNameFilters = hasAppNames || hasSkipAppNames; const appNameForLog = hasAppNames ? ` [${appNames.join(",")}]` : ""; const logs = []; const log = (message, ...optionalParams) => { let message_with_prefix = `${new Date().toISOString().replace("Z", "").replace("T", " ")} [${scriptName}]${appNameForLog} ${message}`; console.log(message_with_prefix, optionalParams); logs.push(message_with_prefix); }; const logError = (message, ...optionalParams) => { if (isError(message)) { let err = message; message = `${err}${err.stack ? (" " + err.stack) : ""}`; } log(`ERROR ${message}`, optionalParams); }; const logErrorVerbose = (message, ...optionalParams) => { if (verbose) { logError(message, optionalParams); } }; const logVerbose = (message) => { if (verbose) { log(message); } }; const getLogLines = () => { return logs.join("\n"); }; const getSystemEvents = () => { let systemEvents = Application("System Events"); systemEvents.includeStandardAdditions = true; return systemEvents; }; const getNotificationCenter = () => { try { @@ -82,7 +93,7 @@ function run(input, parameters) { logError("Could not get NotificationCenter"); throw err; } }; const getNotificationCenterGroups = (retryOnError = false) => { try { @@ -98,20 +109,40 @@ function run(input, parameters) { logError("Could not get NotificationCenter groups"); if (retryOnError) { logError(err); log("Retrying getNotificationCenterGroups..."); return getNotificationCenterGroups(false); } else { throw err; } } }; const isClearButton = (description, name) => { return description === "button" && name === CLEAR_ALL_ACTION_TOP; }; const matchesAnyAppNames = (value, checkValues) => { if (isNullOrEmpty(checkValues)) { return false; } let lowerAppName = value.toLowerCase(); for (let checkValue of checkValues) { if (lowerAppName === checkValue.toLowerCase()) { return true; } } return false; }; const matchesAppName = (role, value) => { if (role !== APP_NAME_MATCHER_ROLE) { return false; } if (hasAppNames) { return matchesAnyAppNames(value, appNames); } return !matchesAnyAppNames(value, skipAppNames); }; const notificationGroupMatches = (group) => { try { @@ -123,7 +154,7 @@ function run(input, parameters) { return false; } if (!V11_OR_GREATER) { let matchedAppName = !hasAppNameFilters; if (!matchedAppName) { for (let elem of group.uiElements()) { if (matchesAppName(elem.role(), elem.description())) { @@ -137,7 +168,7 @@ function run(input, parameters) { } return false; } if (!hasAppNameFilters) { return true; } let firstElem = group.uiElements[0]; @@ -147,7 +178,7 @@ function run(input, parameters) { logErrorVerbose(err); } return false; }; const findCloseActionV10 = (group, closedCount) => { try { @@ -163,7 +194,7 @@ function run(input, parameters) { } log("No close action found for notification"); return null; }; const findCloseAction = (group, closedCount) => { try { @@ -197,7 +228,7 @@ function run(input, parameters) { } log("No close action found for notification"); return null; }; const closeNextGroup = (groups, closedCount) => { try { @@ -222,7 +253,7 @@ function run(input, parameters) { logError("Could not run closeNextGroup"); throw err; } }; try { let groupsCount = getNotificationCenterGroups(true).filter(group => notificationGroupMatches(group)).length; -
lancethomps revised this gist
Apr 6, 2021 . 1 changed file with 52 additions and 30 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -17,6 +17,10 @@ function run(input, parameters) { return !notNull(val); } const isError = (maybeErr) => { return notNull(maybeErr) && (maybeErr instanceof Error || maybeErr.message); } const systemVersion = () => { return Application("Finder").version().split(".").map(val => parseInt(val)); } @@ -42,12 +46,16 @@ function run(input, parameters) { } const logError = (message, ...optionalParams) => { if (isError(message)) { let err = message; message = `${err}${err.stack ? (' ' + err.stack) : ''}`; } log(`ERROR ${message}`, optionalParams); } const logErrorVerbose = (message, ...optionalParams) => { if (verbose) { logError(message, optionalParams); } } @@ -68,18 +76,33 @@ function run(input, parameters) { } const getNotificationCenter = () => { try { return getSystemEvents().processes.byName("NotificationCenter"); } catch (err) { logError("Could not get NotificationCenter"); throw err; } } const getNotificationCenterGroups = (retryOnError = false) => { try { let notificationCenter = getNotificationCenter(); if (notificationCenter.windows.length <= 0) { return []; } if (!V11_OR_GREATER) { return notificationCenter.windows(); } return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements(); } catch (err) { logError("Could not get NotificationCenter groups"); if (retryOnError) { logError(err); return getNotificationCenterGroups(false); } else { throw err; } } } const isClearButton = (description, name) => { @@ -177,33 +200,32 @@ function run(input, parameters) { } const closeNextGroup = (groups, closedCount) => { try { for (let group of groups) { if (notificationGroupMatches(group)) { let closeAction = findCloseAction(group, closedCount); if (notNull(closeAction)) { try { closeAction.perform(); return [true, 1]; } catch (err) { logErrorVerbose(`(group_${closedCount}) Caught error while performing close action, window is probably closed: ${err}`); logErrorVerbose(err); } } return [true, 0]; } } return false; } catch (err) { logError("Could not run closeNextGroup"); throw err; } } try { let groupsCount = getNotificationCenterGroups(true).filter(group => notificationGroupMatches(group)).length; if (groupsCount > 0) { logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`); -
lancethomps revised this gist
Mar 5, 2021 . 1 changed file with 15 additions and 4 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -211,11 +211,22 @@ function run(input, parameters) { let startTime = new Date().getTime(); let closedCount = 0; let maybeMore = true; let maxAttempts = 2; let attempts = 1; while (maybeMore && ((new Date().getTime() - startTime) <= (1000 * 30))) { try { let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount); maybeMore = closeResult[0]; if (maybeMore) { closedCount = closedCount + closeResult[1]; } } catch (innerErr) { if (maybeMore && closedCount === 0 && attempts < maxAttempts) { log(`Caught an error before anything closed, trying ${maxAttempts - attempts} more time(s).`) attempts++; } else { throw innerErr; } } } } else { -
lancethomps revised this gist
Feb 9, 2021 . 1 changed file with 13 additions and 6 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -99,17 +99,24 @@ function run(input, parameters) { if (V11_OR_GREATER && description !== "group") { return false; } if (!V11_OR_GREATER) { let matchedAppName = !hasAppName; if (!matchedAppName) { for (let elem of group.uiElements()) { if (matchesAppName(elem.role(), elem.description())) { matchedAppName = true; break; } } } if (matchedAppName) { return notNull(findCloseActionV10(group, -1)); } return false; } if (!hasAppName) { return true; } let firstElem = group.uiElements[0]; return matchesAppName(firstElem.role(), firstElem.value()); } catch (err) { -
lancethomps revised this gist
Feb 9, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -18,7 +18,7 @@ function run(input, parameters) { } const systemVersion = () => { return Application("Finder").version().split(".").map(val => parseInt(val)); } const systemVersionGreaterThanOrEqualTo = (vers) => { -
lancethomps revised this gist
Feb 9, 2021 . 1 changed file with 100 additions and 29 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,12 @@ function run(input, parameters) { const appName = ""; const verbose = true; const scriptName = "close_notifications_applescript"; const CLEAR_ALL_ACTION = "Clear All"; const CLEAR_ALL_ACTION_TOP = "Clear"; const CLOSE_ACTION = "Close"; const notNull = (val) => { return val !== null && val !== undefined; } @@ -11,12 +17,26 @@ function run(input, parameters) { return !notNull(val); } const systemVersion = () => { return Application("Finder").version().split(".").map(parseInt); } const systemVersionGreaterThanOrEqualTo = (vers) => { return systemVersion()[0] >= vers; } const isBigSurOrGreater = () => { return systemVersionGreaterThanOrEqualTo(11); } const V11_OR_GREATER = isBigSurOrGreater(); const APP_NAME_MATCHER_ROLE = V11_OR_GREATER ? "AXStaticText" : "AXImage"; const hasAppName = notNull(appName) && appName !== ""; const appNameForLog = hasAppName ? ` [${appName}]` : ""; const logs = []; const log = (message, ...optionalParams) => { let message_with_prefix = `${new Date().toISOString().replace("Z", "").replace("T", " ")} [${scriptName}]${appNameForLog} ${message}`; console.log(message_with_prefix, optionalParams); logs.push(message_with_prefix); } @@ -56,40 +76,83 @@ function run(input, parameters) { if (notificationCenter.windows.length <= 0) { return []; } if (!V11_OR_GREATER) { return notificationCenter.windows(); } return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements(); } const isClearButton = (description, name) => { return description === "button" && name === CLEAR_ALL_ACTION_TOP; } const matchesAppName = (role, value) => { return role === APP_NAME_MATCHER_ROLE && value.toLowerCase() === appName.toLowerCase(); } const notificationGroupMatches = (group) => { try { let description = group.description(); if (V11_OR_GREATER && isClearButton(description, group.name())) { return true; } if (V11_OR_GREATER && description !== "group") { return false; } if (!hasAppName) { return true; } if (!V11_OR_GREATER) { for (let elem of group.uiElements()) { if (matchesAppName(elem.role(), elem.description())) { return true; } } return false; } let firstElem = group.uiElements[0]; return matchesAppName(firstElem.role(), firstElem.value()); } catch (err) { logErrorVerbose(`Caught error while checking window, window is probably closed: ${err}`); logErrorVerbose(err); } return false; } const findCloseActionV10 = (group, closedCount) => { try { for (let elem of group.uiElements()) { if (elem.role() === "AXButton" && elem.title() === CLOSE_ACTION) { return elem.actions["AXPress"]; } } } catch (err) { logErrorVerbose(`(group_${closedCount}) Caught error while searching for close action, window is probably closed: ${err}`); logErrorVerbose(err); return null; } log("No close action found for notification"); return null; } const findCloseAction = (group, closedCount) => { try { if (!V11_OR_GREATER) { return findCloseActionV10(group, closedCount); } let checkForPress = isClearButton(group.description(), group.name()); let clearAllAction; let closeAction; for (let action of group.actions()) { let description = action.description(); if (description === CLEAR_ALL_ACTION) { clearAllAction = action; break; } else if (description === CLOSE_ACTION) { closeAction = action; } else if (checkForPress && description === "press") { clearAllAction = action; break; } } if (notNull(clearAllAction)) { @@ -126,28 +189,36 @@ function run(input, parameters) { return false; } try { let notificationCenter = getNotificationCenter(); if (notificationCenter.windows.length <= 0) { logError("No notifications found."); return getLogLines(); } let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length; if (groupsCount > 0) { logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`); let startTime = new Date().getTime(); let closedCount = 0; let maybeMore = true; while (maybeMore && ((new Date().getTime() - startTime) <= (1000 * 30))) { let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount); maybeMore = closeResult[0]; if (maybeMore) { closedCount = closedCount + closeResult[1]; } } } else { throw Error(`No${appNameForLog} notifications found...`); } } catch (err) { logError(err); logError(err.message); getLogLines(); throw err; } return getLogLines(); -
lancethomps revised this gist
Jan 8, 2021 . 1 changed file with 71 additions and 44 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,20 +1,34 @@ function run(input, parameters) { const appName = ""; const verbose = true; const notNull = (val) => { return val !== null && val !== undefined; } const isNull = (val) => { return !notNull(val); } const hasAppName = notNull(appName) && appName !== ""; const appNameForLog = hasAppName ? ` [${appName}]` : ""; const logs = []; const log = (message, ...optionalParams) => { let message_with_prefix = `${new Date().toISOString().replaceAll("Z", "").replaceAll("T", " ")} [close_notifications]${appNameForLog} ${message}`; console.log(message_with_prefix, optionalParams); logs.push(message_with_prefix); } const logError = (message, ...optionalParams) => { log(`ERROR ${message}`, optionalParams); } const logErrorVerbose = (message, ...optionalParams) => { if (verbose) { log(`ERROR ${message}`, optionalParams); } } const logVerbose = (message) => { @@ -23,6 +37,49 @@ function run(input, parameters) { } } const getLogLines = () => { return logs.join("\n"); } const getSystemEvents = () => { let systemEvents = Application("System Events"); systemEvents.includeStandardAdditions = true; return systemEvents; } const getNotificationCenter = () => { return getSystemEvents().processes.byName("NotificationCenter"); } const getNotificationCenterGroups = () => { let notificationCenter = getNotificationCenter(); if (notificationCenter.windows.length <= 0) { return []; } return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements(); } const notificationGroupMatches = (group) => { if (!hasAppName) { return true; } try { for (let elem of group.uiElements()) { if (hasAppName && elem.role() === "AXStaticText" && elem.value().toLowerCase() === appName.toLowerCase()) { return true; } } } catch (err) { logErrorVerbose(`Caught error while checking window, window is probably closed: ${err}`); logErrorVerbose(err); } return false; } const CLEAR_ALL_ACTION = "Clear All"; const CLOSE_ACTION = "Close"; const findCloseAction = (group, closedCount) => { try { let clearAllAction; @@ -41,48 +98,26 @@ function run(input, parameters) { return closeAction; } } catch (err) { logErrorVerbose(`(group_${closedCount}) Caught error while searching for close action, window is probably closed: ${err}`); logErrorVerbose(err); return null; } log("No close action found for notification"); return null; } const closeNextGroup = (groups, closedCount) => { for (let group of groups) { if (notificationGroupMatches(group)) { let closeAction = findCloseAction(group, closedCount); if (notNull(closeAction)) { try { closeAction.perform(); return [true, 1]; } catch (err) { logErrorVerbose(`(group_${closedCount}) Caught error while performing close action, window is probably closed: ${err}`); logErrorVerbose(err); } } return [true, 0]; @@ -91,18 +126,10 @@ function run(input, parameters) { return false; } let notificationCenter = getNotificationCenter(); if (notificationCenter.windows.length <= 0) { logError("No notifications found."); return getLogLines(); } let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length; @@ -123,5 +150,5 @@ function run(input, parameters) { throw Error(`No${appNameForLog} notifications found...`); } return getLogLines(); } -
lancethomps created this gist
Jan 7, 2021 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,127 @@ function run(input, parameters) { const notNull = (val) => { return val !== null && val !== undefined; } const appName = ""; const verbose = true; const CLEAR_ALL_ACTION = "Clear All"; const CLOSE_ACTION = "Close"; const hasAppName = notNull(appName) && appName !== ""; const appNameForLog = hasAppName ? (" " + appName) : ""; const log = (message, ...optionalParams) => { console.log("[close_notifications] " + message, optionalParams); } const logVerbose = (message) => { if (verbose) { log(message); } } const findCloseAction = (group, closedCount) => { try { let clearAllAction; let closeAction; for (let action of group.actions()) { if (action.description() === CLEAR_ALL_ACTION) { clearAllAction = action; break; } else if (action.description() === CLOSE_ACTION) { closeAction = action; } } if (notNull(clearAllAction)) { return clearAllAction; } else if (notNull(closeAction)) { return closeAction; } } catch (err) { logVerbose(`${closedCount}: Caught error while searching for close action, window is probably closed.`); logVerbose(err); return null; } log("No close action found for notification"); return null; } const notificationGroupMatches = (group) => { if (!hasAppName) { return true; } logVerbose(`Checking UI elements of group...`); try { for (let elem of group.uiElements()) { if (hasAppName && elem.role() === "AXStaticText" && elem.value().toLowerCase() === appName.toLowerCase()) { return true; } } } catch (err) { logVerbose(`Caught error while checking window, window is probably closed.`); logVerbose(err); } return false; } const closeNextGroup = (groups, closedCount) => { for (let group of groups) { if (notificationGroupMatches(group)) { logVerbose(`${closedCount}: FIND_CLOSE_ACTION`); let closeAction = findCloseAction(group, closedCount); if (notNull(closeAction)) { logVerbose(`${closedCount}: CLOSING`); try { closeAction.perform(); logVerbose(`${closedCount}: CLOSE_PERFORMED`); return [true, 1]; } catch (err) { logVerbose(`${closedCount}: Caught error while performing close action, window is probably closed.`); logVerbose(err); } } return [true, 0]; } } return false; } const getNotificationCenter = () => { let systemEvents = Application("System Events"); return systemEvents.processes.byName("NotificationCenter"); } const getNotificationCenterGroups = () => { return getNotificationCenter().windows[0].uiElements[0].uiElements[0].uiElements(); } let notificationCenter = getNotificationCenter(); if (notificationCenter.windows.length <= 0) { return input; } let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length; if (groupsCount > 0) { logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`); let closedCount = 0; let maybeMore = true; while (maybeMore) { let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount); maybeMore = closeResult[0]; if (maybeMore) { closedCount = closedCount + closeResult[1]; } } } else { throw Error(`No${appNameForLog} notifications found...`); } return input; }