https://github.com/bkw777/notify-send.sh does it
Pure bash other than using gdbus call
to do the actual dbus transaction.
It's main reason for existing is actually to replace existing notification,
so the readme shows exactly that example.
Aside from reading the code, you can enable debugging and read the final gdbus command out of the debug log.
The gdbus commandline 2nd to last arg contains $h, and backtrack from there $h is built from ${HINTS[*]}, which is built by one or more calls to process_hint and make_hint (returns it's output via global $_r to avoid subshells). There is always at least one to set the urgency level even if you don't supply any --hint options.
To replace a notification, you need to know it's ID, and to know it's ID you have to collect it when it was created the first time. (or you could try to just generte your own ID which you hope will be unique and never overwrite some other notification, but the clean way is to let the notification daemon generate the notification the first time, and then use that to update it after that.)
Send a notification and collect it's ID
with debugging enabled so you can see the generated gdbus command
$ DEBUG_NOTIFY_SEND=true notify-send.sh --print-id --expire-time=0 --close-action="mainline-gtk --install 6.3.4" "New Kernel" "Install 6.3.4"
/usr/local/bin/notify-send.sh debug logging to /run/user/1000/.notify-send.sh.1044020.e
68
$
notification ID was 68
gdbus command was:
$ grep "gdbus call" /run/user/1000/.notify-send.sh.1044020.e
++ gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify -- notify-send.sh 0 '' 'New Kernel' 'Install 6.3.4' '[]' '{"urgency":<byte 1>}' 0
$
now replace that notification in-place, using --replace=68
$ DEBUG_NOTIFY_SEND=true notify-send.sh --replace=68 --expire-time=0 --close-action="mainline-gtk --install 6.3.5" "New Kernel" "Install 6.3.5"
/usr/local/bin/notify-send.sh debug logging to /run/user/1000/.notify-send.sh.1044042.e
$ grep "gdbus call" /run/user/1000/.notify-send.sh.1044042.e
++ gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify -- notify-send.sh 68 '' 'New Kernel' 'Install 6.3.5' '[]' '{"urgency":<byte 1>}' 0
$
So hints are of the form: {'name':<type value>}
with some non-obvious rules and allowed deviations:
the entire string has to be enclosed in quotes or escaped with backslashes since this is all on a bash command line, and the exact syntax is "whatever you want that results in a valid bash commandline..." since there's more than one way to quote things. Exept one really non-obvious, name must be individually quoted, single or double, even if it has no spaces, name's quotes must themselves be either escaped or quoted so that bash doesn't eat them so they become literals and part of the string.
The script is generating: '{"urgency":<byte 1>}'
also valid: "{'urgency':<byte 1>}"
also valid: "{\"urgency\":<byte 1>}"
NOT valid: \{'urgency':\<byte\ 1\>\}
IS valid: \{\'urgency\':\<byte\ 1\>\}
type is optional, at least for some types, at least for byte and int32
valid: "{'urgency':<byte 1>}"
also valid: "{'urgency':<1>}"
https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#hints has a table that shows all the types as BYTE INT32 STRING etc, but they must actually be sent in lower-case.
valid: "{'urgency':<byte 1>}"
not valid: "{'urgency':<BYTE 1>}"
Not shown yet but multiple hint items are comma seperated within the braces
"{\"urgency\":<byte 1>,\"category\":<string \"info\">}"
Here's another with more stuff filled in, added an icon name and another hint for category, and action buttons so all fields have stuff in them, and actions and hints are both multi-item lists:
$ notify-send.sh --expire-time=0 --force-expire --category=info --icon=mainline --action="Mainline App:mainline-gtk" --action="Install 6.3.4:mainline-gtk --install 6.3.4" "Mainlin Kernels" "New kernel available"
/usr/local/bin/notify-send.sh debug logging to /run/user/1000/.notify-send.sh.1148819.e
$ grep "gdbus call" /run/user/1000/.notify-send.sh.1148819.e
++ gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify -- notify-send.sh 0 mainline 'Mainlin Kernels' 'New kernel available' '["0","Mainline App","1","Install 6.3.4"]' '{"urgency":<byte 1>,"category":<string "info">}' 0
$
You may have noticed that these examples include an action that doesn't show up in the gdbus command.
Actions get handled by setting up a gdbus monitor command, and grepping the notification ID from the monitor process's output.
The gdbus monitor will output multiple messages, and you ignore any that don't have your ID. When you get a record with your ID in it, parse the action out of that line, and depending upon what the action was, maybe run the command you were previously given.
The action commandline is never written to dbus. What happens is notify-send.sh runs notify-action.sh and notify-action.sh waits for essentially "notification ID 68 closed" and when it sees that, it runs the command that notify-send.sh gave it previously.
If you use an action button instead of close-action, you give that button some unique key (you make it up, can be anything, simplest is just a number, one for each button, can start from the same 0 or 1 every time since it only needs to be unique per notification ID, so 3 buttons can be keys 1 2 3), and that goes onto dbus, and later the watcher process looks for essentially "notification 68 got action 2" and notify-action.sh has previously been given a list of button IDs and associated commands, so when it sees "got ID 68 action 2" it runs the command for action 2.
$i
in your original bash script? – muru Jun 20 '16 at 06:20'value': 'i'
, for the stringi
, or'value': $i
, so thati
's value is passed on (if an integer). – muru Jun 20 '16 at 06:30"{'String': <'variant_value'>, 'String2': <'variant_value'>}"
. "Did you try with that? See http://askubuntu.com/questions/359587 – Khurshid Alam Jun 28 '16 at 16:38