Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save arielazem/7f8b18e5f7ea32ed7d7eac22e3e6e6b9 to your computer and use it in GitHub Desktop.
Save arielazem/7f8b18e5f7ea32ed7d7eac22e3e6e6b9 to your computer and use it in GitHub Desktop.

Revisions

  1. @lancethomps lancethomps revised this gist Jan 7, 2023. No changes.
  2. @lancethomps lancethomps revised this gist Jan 6, 2023. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion close_notifications_applescript.js
    Original 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();
    }
    return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements();
    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) {
  3. @lancethomps lancethomps revised this gist Mar 2, 2022. 1 changed file with 58 additions and 27 deletions.
    85 changes: 58 additions & 27 deletions close_notifications_applescript.js
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    function run(input, parameters) {

    const appName = "";
    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 hasAppName = notNull(appName) && appName !== "";
    const appNameForLog = hasAppName ? ` [${appName}]` : "";
    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) : ''}`;
    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) => {
    return role === APP_NAME_MATCHER_ROLE && value.toLowerCase() === appName.toLowerCase();
    }
    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 = !hasAppName;
    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 (!hasAppName) {
    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;
  4. @lancethomps lancethomps revised this gist Apr 6, 2021. 1 changed file with 52 additions and 30 deletions.
    82 changes: 52 additions & 30 deletions close_notifications_applescript.js
    Original 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) {
    log(`ERROR ${message}`, optionalParams);
    logError(message, optionalParams);
    }
    }

    @@ -68,18 +76,33 @@ function run(input, parameters) {
    }

    const getNotificationCenter = () => {
    return getSystemEvents().processes.byName("NotificationCenter");
    try {
    return getSystemEvents().processes.byName("NotificationCenter");
    } catch (err) {
    logError("Could not get NotificationCenter");
    throw err;
    }
    }

    const getNotificationCenterGroups = () => {
    let notificationCenter = getNotificationCenter();
    if (notificationCenter.windows.length <= 0) {
    return [];
    }
    if (!V11_OR_GREATER) {
    return notificationCenter.windows();
    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;
    }
    }
    return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements();
    }

    const isClearButton = (description, name) => {
    @@ -177,33 +200,32 @@ function run(input, parameters) {
    }

    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);
    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 [true, 0];
    }
    return false;
    } catch (err) {
    logError("Could not run closeNextGroup");
    throw err;
    }
    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;
    let groupsCount = getNotificationCenterGroups(true).filter(group => notificationGroupMatches(group)).length;

    if (groupsCount > 0) {
    logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`);
  5. @lancethomps lancethomps revised this gist Mar 5, 2021. 1 changed file with 15 additions and 4 deletions.
    19 changes: 15 additions & 4 deletions close_notifications_applescript.js
    Original 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))) {
    let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount);
    maybeMore = closeResult[0];
    if (maybeMore) {
    closedCount = closedCount + closeResult[1];
    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 {
  6. @lancethomps lancethomps revised this gist Feb 9, 2021. 1 changed file with 13 additions and 6 deletions.
    19 changes: 13 additions & 6 deletions close_notifications_applescript.js
    Original 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 (!hasAppName) {
    return true;
    }
    if (!V11_OR_GREATER) {
    for (let elem of group.uiElements()) {
    if (matchesAppName(elem.role(), elem.description())) {
    return true;
    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) {
  7. @lancethomps lancethomps revised this gist Feb 9, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion close_notifications_applescript.js
    Original 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(parseInt);
    return Application("Finder").version().split(".").map(val => parseInt(val));
    }

    const systemVersionGreaterThanOrEqualTo = (vers) => {
  8. @lancethomps lancethomps revised this gist Feb 9, 2021. 1 changed file with 100 additions and 29 deletions.
    129 changes: 100 additions & 29 deletions close_notifications_applescript.js
    Original 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().replaceAll("Z", "").replaceAll("T", " ")} [close_notifications]${appNameForLog} ${message}`;
    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 notificationGroupMatches = (group) => {
    if (!hasAppName) {
    return true;
    }
    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 {
    for (let elem of group.uiElements()) {
    if (hasAppName && elem.role() === "AXStaticText" && elem.value().toLowerCase() === appName.toLowerCase()) {
    return true;
    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 CLEAR_ALL_ACTION = "Clear All";
    const CLOSE_ACTION = "Close";
    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()) {
    if (action.description() === CLEAR_ALL_ACTION) {
    let description = action.description();
    if (description === CLEAR_ALL_ACTION) {
    clearAllAction = action;
    break;
    } else if (action.description() === CLOSE_ACTION) {
    } 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;
    }

    let notificationCenter = getNotificationCenter();
    if (notificationCenter.windows.length <= 0) {
    logError("No notifications found.");
    return getLogLines();
    }
    try {
    let notificationCenter = getNotificationCenter();
    if (notificationCenter.windows.length <= 0) {
    logError("No notifications found.");
    return getLogLines();
    }

    let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length;
    let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length;

    if (groupsCount > 0) {
    logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`);
    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];
    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...`);
    }
    } else {
    throw Error(`No${appNameForLog} notifications found...`);
    } catch (err) {
    logError(err);
    logError(err.message);
    getLogLines();
    throw err;
    }

    return getLogLines();
  9. @lancethomps lancethomps revised this gist Jan 8, 2021. 1 changed file with 71 additions and 44 deletions.
    115 changes: 71 additions & 44 deletions close_notifications_applescript.js
    Original 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 appName = "";
    const verbose = true;

    const CLEAR_ALL_ACTION = "Clear All";
    const CLOSE_ACTION = "Close";
    const isNull = (val) => {
    return !notNull(val);
    }

    const hasAppName = notNull(appName) && appName !== "";
    const appNameForLog = hasAppName ? (" " + appName) : "";
    const appNameForLog = hasAppName ? ` [${appName}]` : "";

    const logs = [];
    const log = (message, ...optionalParams) => {
    console.log("[close_notifications] " + 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) {
    logVerbose(`${closedCount}: Caught error while searching for close action, window is probably closed.`);
    logVerbose(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 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);
    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;
    }

    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;
    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 input;
    return getLogLines();
    }
  10. @lancethomps lancethomps created this gist Jan 7, 2021.
    127 changes: 127 additions & 0 deletions close_notifications_applescript.js
    Original 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;
    }