Dan Weaver
Dan Weaver

Reputation: 731

How to listen for, and act upon, a Mac notification using Automator?

Is it possible to listen for a specific notification on Mac and act upon it using Automator?

I regularly use an app that runs a background job then sends a notification when it's finished. The app stays open after the job is finished so I'd like to use Automator to quit the app when the notification is received.

If it's not possible in Automator is there another way I could do this?

More context: the app is actually launched by a Folder Action created using Automator. It detects when a specific SD card is inserted and runs a backup app on that SD card. So maybe there's something I can add to that Folder Action workflow that can detect the notification?

Upvotes: 1

Views: 1774

Answers (1)

johsoderi
johsoderi

Reputation: 51

While it's certainly possible to query the sqlite database containing notifications in macOS, it seems to me like an unnecessarily complicated route, and I would first try the following...

In your workflow, add a 'Run Shell Script' action at the end, containing something like this:

while [ $(ps -e | grep "[N]ameOfBackgroundProcess" | wc -l) -gt 0 ]; do
    sleep 3
done
killall "NameOfAppToQuit" 1&>2 /dev/null

The while loop checks whether the background job is still running.

ps -e lists all running processes.

grep "[N]ameOf..." gets all lines containing the name. Brackets around the first letter excludes the grep process itself from the output.

wc -l counts the lines.

-gt 0 checks if the number is greater than zero.

When the loop is done, that means the process has exited so we quit the app with killall.

As for the notification route...

I haven't figured everything out, but this might give you a head start:

#!/usr/bin/env bash

# Get the directory of the Notification Center database (works for me in Big Sur):
db_dir=$(lsof -p $(ps aux | grep -m1 usernoted | awk '{ print $2 }')| awk '{ print $NF }' | grep 'db2/db$' | xargs dirname)

# Get the app_id:
app_id=$(sqlite3 "$db_dir"/db 'SELECT app_id FROM app WHERE identifier="com.example.identifier";')

# Get relevant records:
sqlite3 "$db_dir"/db "SELECT * FROM record WHERE app_id='$app_id';"

# And this is where I leave you.

To explore the database in a GUI, try https://sqlitebrowser.org/

Upvotes: 2

Related Questions