Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get DND state (as setting DND state) is not working anymore on mac os v.11 (Big Sur) #9

Open
RihardKrauz opened this issue Sep 14, 2020 · 29 comments

Comments

@RihardKrauz
Copy link

RihardKrauz commented Sep 14, 2020

getDoNotDisturb is not working anymore on mac os v.11 (Big Sur) since they removed ~/Library/Preferences/ByHost/com.apple.notificationcenterui setting

@RihardKrauz RihardKrauz changed the title Get DND state (as setting DND state) not works anymore on os x v.11 (Big Sur) Get DND state (as setting DND state) is not working anymore on mac os v.11 (Big Sur) Sep 14, 2020
agross added a commit to agross/dotfiles that referenced this issue Nov 13, 2020
I.e. there does not seem to be an officially supported way. I delegate
toggling DND (not idempotent!) to BetterTouchTool until I find a better
solution.

sindresorhus/do-not-disturb#9
@a7madgamal
Copy link

a7madgamal commented Nov 20, 2020

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

@PhilipDukhov
Copy link

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)
}

@CharlieHess
Copy link

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: felixrieseberg/macos-notification-state#15

@alse
Copy link

alse commented Dec 28, 2020

@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

@tiiiecherle
Copy link

tiiiecherle commented Jan 3, 2021

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.

@mellson
Copy link

mellson commented Jan 4, 2021

Nice one @tiiiecherle thanks for posting this!

@tiiiecherle
Copy link

@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

@vitorgalvao
Copy link

vitorgalvao commented Jan 22, 2021

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).

@tiiiecherle
Copy link

tiiiecherle commented Jan 27, 2021

@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.

@karlhorky
Copy link

@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

@tiiiecherle
Copy link

@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

Repository owner deleted a comment from ibc Sep 16, 2021
@karlhorky
Copy link

karlhorky commented Oct 26, 2021

Edit, see comments below:

I just updated to macOS 12 Monterey and can confirm that the solution from @tiiiecherle still works! 🙌

@agross
Copy link

agross commented Oct 26, 2021

@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.

@karlhorky
Copy link

@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

@agross
Copy link

agross commented Oct 26, 2021

@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.

@nbashkankov
Copy link

@agross - same for me - Monterey has new Focus mode stuff - see #12

@karlhorky
Copy link

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...

@vitorgalvao
Copy link

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.

@karlhorky
Copy link

karlhorky commented Nov 18, 2021

Ah, just came up with an easy and elegant solution using macOS Monterey Shortcuts 🎉

  1. Open Shortcuts.app
  2. Create a shortcut that ONLY turns on the Focus mode "Do Not Disturb" (rename this to be dnd-on)
  3. Create a shortcut that ONLY turns off the Focus mode "Do Not Disturb" (rename this to be dnd-on)
  4. Run shortcut run dnd-on on the command line to turn on Do Not Disturb
  5. Run shortcut run dnd-off on the command line to turn off Do Not Disturb

Screenshots / videos:

2021-11-18_19-21

2021-11-18_19-19

Screen Shot 2021-11-18 at 19 17 39

kap3.mp4

@vitorgalvao
Copy link

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.

@karlhorky
Copy link

karlhorky commented Nov 18, 2021

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)

@vitorgalvao
Copy link

To get Do not Disturb state: vitorgalvao/tiny-scripts#206 (comment)

@tiiiecherle
Copy link

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.

@vitorgalvao
Copy link

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'

@tiiiecherle
Copy link

@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.

@vitorgalvao
Copy link

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.

@tiiiecherle
Copy link

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.

@arodik
Copy link

arodik commented Dec 12, 2021

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 🎉 🎉 🎉

@john-preston
Copy link

I hope I've fixed that for the next version, need to check in the next 4.6.11 beta when it's out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests