Open RihardKrauz opened 4 years ago
took a look at the issue, here is where I THINK the value is, but I'm stuck trying to update the UI to apply the change (works with logout though) https://gist.github.com/a7madgamal/9d3518a62c21477a92be461fbd652533
value for key dnd_prefs
at com.apple.ncprefs.plist
is data representations of an other plist! The minus is that it's not updated instantly, takes a couple of seconds. This is how I parse it using swift:
import Foundation
let ncprefsUrl = URL(
fileURLWithPath: NSString(
"~/Library/Preferences/com.apple.ncprefs.plist"
).expandingTildeInPath
)
func plistFromData(_ data: Data) throws -> [String:Any] {
try PropertyListSerialization.propertyList(
from: data,
format: nil
) as! [String:Any]
}
let prefsList = try plistFromData(try Data(contentsOf: ncprefsUrl))
let dndPrefsData = prefsList["dnd_prefs"] as! Data
let dndPrefsList = try plistFromData(dndPrefsData)
// exit with 1 if dnd, 0 otherwise
if let userPref = dndPrefsList["userPref"] as? [String:Any] {
print(userPref)
exit(userPref["enabled"] as! Int32)
} else {
exit(0)
}
sharing here as many others will surely stumble upon this thread. here's the Objective-C version of parsing that nested plist, also handles the scheduled prefs: https://github.com/felixrieseberg/macos-notification-state/pull/15
@a7madgamal any luck on updating the UI after the change?
I tried something similar to commitChanges with a 'com.apple.ncprefs' appid / notification name but couldn't get it to work
took a look at the issue, here is where I THINK the value is, but I'm stuck trying to update the UI to apply the change (works with logout though) https://gist.github.com/a7madgamal/9d3518a62c21477a92be461fbd652533
Thanks for sharing, I found out the commands to trigger the new state. Just use your commands to enable or disable followed by:
killall usernoted
killall ControlCenter
Works perfectly on macOS 11.1 ;)
Edit: I added a second kill command as it seems necessary if triggering the dnd for the first time after reboot.
Nice one @tiiiecherle thanks for posting this!
@mellson You're welcome, I'm glad I could help.
I was trying to find a solution myself when I found this issue and @a7madgamal 's solution.
After quite some time today I also found out how to get the correct values on the command line...
/usr/libexec/PlistBuddy -x -c 'Print "dnd_prefs"' /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist | xmllint --xpath "string(//data)" - | base64 --decode | xxd -p
or
plutil -extract dnd_prefs xml1 -o - /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist | xmllint --xpath "string(//data)" - | base64 --decode | xxd -p
For those looking for a standalone solution, I’ve studied options out there (including this thread; thank you all for the previous research) and made a script which works robustly. It doesn’t require additional software (everything ships with macOS) and is only for Big Sur.
If you use Homebrew, you can install it with brew install vitorgalvao/tiny-scripts/calm-notifications
. Do calm-notifications --help
to see available options (on
, off
, toggle
, status
).
@vitorgalvao Thanks for the script and the information. I updated the necessary commands for zsh and added them to my macos system preferences configuration script for documentation purposes.
For anyone who needs them in a shell script, this works for me in zsh with the new additions:
check_dnd_status() {
DND_STATUS=$(plutil -extract dnd_prefs xml1 -o - /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist | xmllint --xpath "string(//data)" - | base64 --decode | plutil -convert xml1 - -o - | xmllint --xpath 'boolean(//key[text()="userPref"]/following-sibling::dict/key[text()="enabled"])' -)
}
check_dnd_status
enable_dnd() {
defaults read /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist >/dev/null
DND_HEX_DATA=$(plutil -extract dnd_prefs xml1 -o - /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist | xmllint --xpath "string(//data)" - | base64 --decode | plutil -convert xml1 - -o - | plutil -insert userPref -xml "
<dict>
<key>date</key>
<date>$(date -u +"%Y-%m-%dT%H:%M:%SZ")</date>
<key>enabled</key>
<true/>
<key>reason</key>
<integer>1</integer>
</dict> " - -o - | plutil -convert binary1 - -o - | xxd -p | tr -d '\n')
defaults write com.apple.ncprefs.plist dnd_prefs -data "$DND_HEX_DATA"
PROCESS_LIST=(
#cfprefsd
usernoted
#NotificationCenter
)
while IFS= read -r line || [[ -n "$line" ]]
do
if [[ "$line" == "" ]]; then continue; fi
i="$line"
#echo "$i"
if [[ $(ps aux | grep "$i" | grep -v grep | awk '{print $2;}') != "" ]]
then
killall "$i" && sleep 0.1 && while [[ $(ps aux | grep "$i" | grep -v grep | awk '{print $2;}') == "" ]]; do sleep 0.5; done
else
:
fi
done <<< "$(printf "%s\n" "${PROCESS_LIST[@]}")"
#sleep 2
}
enable_dnd
disable_dnd() {
defaults read /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist >/dev/null
DND_HEX_DATA=$(plutil -extract dnd_prefs xml1 -o - /Users/"$USER"/Library/Preferences/com.apple.ncprefs.plist | xmllint --xpath "string(//data)" - | base64 --decode | plutil -convert xml1 - -o - | plutil -remove userPref - -o - | plutil -convert binary1 - -o - | xxd -p | tr -d '\n')
defaults write com.apple.ncprefs.plist dnd_prefs -data "$DND_HEX_DATA"
PROCESS_LIST=(
#cfprefsd
usernoted
#NotificationCenter
)
while IFS= read -r line || [[ -n "$line" ]]
do
if [[ "$line" == "" ]]; then continue; fi
i="$line"
#echo "$i"
if [[ $(ps aux | grep "$i" | grep -v grep | awk '{print $2;}') != "" ]]
then
killall "$i" && sleep 0.1 && while [[ $(ps aux | grep "$i" | grep -v grep | awk '{print $2;}') == "" ]]; do sleep 0.5; done
else
:
fi
done <<< "$(printf "%s\n" "${PROCESS_LIST[@]}")"
#sleep 2
}
disable_dnd
EDIT: I updated the functions after some testing. They seem to work reliably now.
@tiiiecherle thanks for this! I've used this in this script to automatically stop and start Do Not Disturb when Zoom calls are running, seems to be working well!
https://github.com/karlhorky/do-not-disturb-during-zoom-macos
@karlhorky You are welcome. I'm glad I could help.
Big credits and thanks go to everyone who posted here and gave the needed ideas and input, e.g. @a7madgamal and @vitorgalvao
Edit, see comments below:
I just updated to macOS 12 Monterey and can confirm that the solution from @tiiiecherle still works! 🙌
@karlhorky @tiiiecherle For me both enabling and disabling do not work on Monterey. Focus mode/DND stays the way it is set via the UI.
@agross interesting, wonder what's different between your system and mine.
Here's the script that I am using to trigger that code:
https://github.com/karlhorky/do-not-disturb-during-zoom-macos
@karlhorky I don't know either, but I have two Macs that show the same behavior. Getting the DND status does not change regardless of the Focus Mode setting.
@agross - same for me - Monterey has new Focus mode stuff - see #12
Yeah weirdly enough, the solution from @tiiiecherle stopped working for me on Monterey... 😫
Maybe it never worked, and I just tricked myself into thinking it was working...
Yeah weirdly enough, the solution from @tiiiecherle stopped working for me on Monterey...
It’s not weird at all. Programmatically setting Do Not Disturb isn’t simple and Apple keeps breaking methods we come up with. Big Sur required a whole new method, and so will Monterey.
Maybe it never worked, and I just tricked myself into thinking it was working...
Seems like the likeliest explanation.
Ah, just came up with an easy and elegant solution using macOS Monterey Shortcuts 🎉
dnd-on
)dnd-on
)shortcut run dnd-on
on the command line to turn on Do Not Disturbshortcut run dnd-off
on the command line to turn off Do Not DisturbScreenshots / videos:
https://user-images.githubusercontent.com/1935696/142481782-06731f84-4012-482a-9cdb-075afa95df59.mp4
I’ve been thinking the same, that Shortcuts would be the solution going forward. At least we no longer need to worry about Apple breaking our solutions every time.
Though that likely does not provide a way to check the state of Do Not Disturb.
I’m still on Big Sur so can’t check.
Though that likely does not provide a way to check the state of Do Not Disturb.
Right, that makes sense, although apparently SiriKit can query the state - also macOS via Mac Catalyst 15.0+ (the focusStatus
API) (maybe macOS gets this capability too, or already has it but is undocumented)
To get Do not Disturb state: https://github.com/vitorgalvao/tiny-scripts/issues/206#issuecomment-974747114
Thanks to everyone for all the updates and the hints.
I also decided to go with the Shortcuts.app when using macOS12 and updated all my scripts accordingly.
Checking status and turning on and off seems to work reliably after some testing and a first time configuration of the Shortcuts.app.
WIth this Shortcut, you can give it as input on
, off
, or a number (representing minutes to stay active). Example:
shortcuts run 'Calm Notifications' <<< 'on'
@vitorgalvao Thanks for the hint. I am not an Alfred Powerpack user, but I will keep it in mind. The workflow with shortcuts.app and the command line seems to work fine.
The workflow with shortcuts.app and the command line seems to work fine.
That’s why I shared the link to the relevant file. While I do provide it as part of an Alfred tool, it can be downloaded and used independently.
Thanks, but how and where do I install the workflow? Alfred states on it's website that you have to be a powerpack user to use workflows.
Hey folks, I've created a library for shortcut-based focus mode management. https://github.com/arodik/macos-focus-mode
@vitorgalvao I've used your shortcut if you don't mind) Thank you 🎉 🎉 🎉
I hope I've fixed that for the next version, need to check in the next 4.6.11 beta when it's out.
getDoNotDisturb is not working anymore on mac os v.11 (Big Sur) since they removed ~/Library/Preferences/ByHost/com.apple.notificationcenterui setting