Search code examples
bashdbus

Extract title and message from the output of dbus-monitor


I'm writing a bash script that executes a command every time a notification is triggered from the system and I'm using the output of dbus-monitor "interface='org.freedesktop.Notifications'".

I'm struggling to extract only title and message from the output of that command, could you please help me to do that?

I tried to do:

dbus-monitor "interface='org.freedesktop.Notifications'" |
  grep --line-buffered "string" |
  grep --line-buffered -e method -e ":" -e '""' -e urgency -e notify -v |
  grep --line-buffered '.*(?=string)|(?<=string).*' -oPi |
  grep --line-buffered -v '^\s*$' |
  grep --line-buffered -wvi 'image-data\|variant\|desktop-entry\|activate\|default\|sender-pid' |
  while read -r LINE; do
      printf "$LINE\n\n"
      # ...other commands...
  done

and it prints something like:

"Firefox"
"<message from Firefox>"
"Firefox"
"Firefox"
// ...

so that's not exactly what I want to accomplish!

Any help is appreciated!

Thanks

edit:

example of the dbus-monitor:

signal time=1668013439.676960 sender=org.freedesktop.DBus -> destination=:1.1820 serial=4294967295 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
   string ":1.1820"
method call time=1668013457.635273 sender=:1.131 -> destination=:1.56 serial=704 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=Notify
   string "Firefox"
   uint32 0
   string ""
   string "<message1>"
   string "<message2>"
   array [
      string "default"
      string "Activate"
   ]
   array [
      dict entry(
         string "desktop-entry"
         variant             string "Firefox"
      )
      dict entry(
         string "image-data"
         variant             struct {
               int32 48
               int32 48
               int32 192
               boolean true
               int32 8
               int32 4
               array of bytes [
                  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                  ...
               ]
            }
      )
   ]
   int32 -1

I'd like to extract:

Title: "Firefox"
Message: <message1>, <message2>
Time: <date of receiving>

Solution

  • You could use GNU awk for this task:

    dbus-monitor "interface='org.freedesktop.Notifications'" |
    awk '
        $1 == "signal" {
            if (state) emit()
            state = 0
            _title = ""
            _messages = ""
            split($2,arr,"=")
            _date = strftime("%Y-%m-%dT%H:%M:%S%z",arr[2])
    
            next
        }
        $1 == "method" { state = 1; next; }
        $1 == "string" && (state == 1 || state == 2) && match($0,/".+"/) {
            s = substr($0,RSTART,RLENGTH)
            if (state == 1) {
                _title = s
                state = 2
                next
            } else
                _messages = (_messages == "" ? "" : _messages ", ") s
        }
        $1 == "array" { state = 3 }
        END { if (state) emit() }
        function emit() {
            print "Title:", _title
            print "Message:", _messages
            print "Date: " _date
            fflush()
        }
    '
    

    remark: the input format isn't clear to me so the current state machine might be inaccurate; it works with the example though

    Title: "Firefox"
    Message: "<message1>", "<message2>"
    Date: 2022-11-09T12:03:59-0500