Last active
July 25, 2024 09:36
-
-
Save drewkerr/0f2b61ce34e2b9e3ce0ec6a92ab05c18 to your computer and use it in GitHub Desktop.
Read the current Focus mode on macOS Monterey (12.0+) using JavaScript for Automation (JXA)
This file contains 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
const app = Application.currentApplication() | |
app.includeStandardAdditions = true | |
function getJSON(path) { | |
const fullPath = path.replace(/^~/, app.pathTo('home folder')) | |
const contents = app.read(fullPath) | |
return JSON.parse(contents) | |
} | |
function run() { | |
let focus = "No focus" // default | |
const assert = getJSON("~/Library/DoNotDisturb/DB/Assertions.json").data[0].storeAssertionRecords | |
const config = getJSON("~/Library/DoNotDisturb/DB/ModeConfigurations.json").data[0].modeConfigurations | |
if (assert) { // focus set manually | |
const modeid = assert[0].assertionDetails.assertionDetailsModeIdentifier | |
focus = config[modeid].mode.name | |
} else { // focus set by trigger | |
const date = new Date | |
const now = date.getHours() * 60 + date.getMinutes() | |
for (const modeid in config) { | |
const triggers = config[modeid].triggers.triggers[0] | |
if (triggers && triggers.enabledSetting == 2) { | |
const start = triggers.timePeriodStartTimeHour * 60 + triggers.timePeriodStartTimeMinute | |
const end = triggers.timePeriodEndTimeHour * 60 + triggers.timePeriodEndTimeMinute | |
if (start < end) { | |
if (now >= start && now < end) { | |
focus = config[modeid].mode.name | |
} | |
} else if (start > end) { // includes midnight | |
if (now >= start || now < end) { | |
focus = config[modeid].mode.name | |
} | |
} | |
} | |
} | |
} | |
return focus | |
} |
I'm running the script on Ventura 13.4.1, and I get:[ ](focus.js: execution error: Error: Error: Can't convert types. (-1700))
Not sure. It's working for me on the same version, running in Script Editor and Shortcuts, as long as Full Disk Access is allowed in System Settings (siriactionsd
, in the case of Shortcuts). This isn't meant to be much more than a hack though.
I use the following Alfred Workflow in order to enable/disable DND: https://github.com/vitorgalvao/calm-notifications-workflow/tree/main/Workflow
It uses its own Shortcut
under the hood that needs to be installed first.
I post it here as an example of a working implementation that people can look into.
Python if you want in that context.
#!/usr/bin/env python3
import json
import os
import datetime
ASSERT_PATH = os.path.expanduser("~/Library/DoNotDisturb/DB/Assertions.json")
MODECONFIG_PATH = os.path.expanduser("~/Library/DoNotDisturb/DB/ModeConfigurations.json")
def get_focus():
focus = "No focus" #default
assertJ = json.load(open(ASSERT_PATH))['data'][0]['storeAssertionRecords']
configJ = json.load(open(MODECONFIG_PATH))['data'][0]['modeConfigurations']
if assertJ:
modeid = assertJ[0]['assertionDetails']['assertionDetailsModeIdentifier']
focus = configJ[modeid]['mode']['name']
else:
date = datetime.datetime.today()
now = date.hour * 60 + date.minute
for modeid in configJ:
triggers = configJ[modeid]['triggers']['triggers'][0]
if triggers and triggers['enabledSetting'] == 2:
start = triggers['timePeriodStartTimeHour'] * 60 + triggers['timePeriodStartTimeMinute']
end = triggers['timePeriodEndTimeHour'] * 60 + triggers['timePeriodEndTimeMinute']
if start < end:
if now >= start and now < end:
focus = configJ[modeid]['mode']['name']
elif start > end: # includes midnight
if now >= start or now < end:
focus = configJ[modeid]['mode']['name']
return focus
if '__main__' == __name__:
print(get_focus())
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Doesn't seem to return active focus mode name if its been set from another device (in my case an iPhone).
MacOS does recognise its in a Focus mode on the menubar but the script returns:
❯ osascript -l JavaScript ~/scripts/get-focus-mode.js
No focus
Contents of ~/Library/DoNotDisturb/DB/ModeConfigurations.json for active Work mode are:
"com.apple.focus.work": { "triggers": { "triggers": [] }, "automaticallyGenerated": false, "mode": { "name": "Work", "tintColorName": "systemTealColor", "identifier": "<REMOVED>", "semanticType": 4, "symbolImageName": "person.lanyardcard.fill", "modeIdentifier": "com.apple.focus.work", "visibility": 0 }, "dimsLockScreen": 0, "configuration": { "suppressionType": 2, "compatibilityVersion": 3, "configurationType": 0, "minimumBreakthroughUrgency": 1, "hideApplicationBadges": 1 }, "created": 1671056911.476048, "compatibilityVersion": 2, "hasSecureData": true, "impactsAvailability": 0, "lastModified": 1674036685.879897 },
Which suggests that its not matching the following condition:
if (triggers && triggers.enabledSetting == 2)
Maybe a focus mode triggered via geo-location doesn't get written out to ~/Library/DoNotDisturb/DB/ModeConfigurations.json ?