Escuchar notificaciones entrantes de libnotify usando DBus

9

Estoy intentando filtrar cada notificación a través de espeak. Sin embargo, parece que no puedo encontrar una manera de obtener el cuerpo de notificación de un script de Python, ni siquiera qué nombre_de_ señal escuchar.

bus.add_signal_receiver(espeak,
                    dbus_interface="org.freedesktop.Notifications",
                    signal_name="??")

Intentar buscar en Google esto solo parece arrojar resultados que implican la creación de nuevas notificaciones, así que ahora estoy completamente perdido.

Alguien me puede ayudar con esto?

En resumen, lo que quiero es escuchar las notificaciones entrantes usando python y obtener el atributo "cuerpo" de la notificación.

hombre máquina
fuente
1
Parece que una notificación no produce una señal, es decir, dbus-monitor "type='signal',interface='org.freedesktop.Notifications'"no muestra nada pero dbus-monitor "interface='org.freedesktop.Notifications'"muestra notificaciones (el tipo es 'method_call' no 'signal').
jfs

Respuestas:

11

Para mantener esto actualizado: desde dbus 1.5 se requiere un parámetro adicional al agregar una cadena de coincidencia bus.add_match_string_non_blockingpara asegurarse de que recibimos todo.

El código resultante sería el siguiente:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def notifications(bus, message):
    print [arg for arg in message.get_args_list()]

DBusGMainLoop(set_as_default=True)

bus = dbus.SessionBus()
bus.add_match_string_non_blocking("eavesdrop=true, interface='org.freedesktop.Notifications', member='Notify'")
bus.add_message_filter(notifications)

mainloop = glib.MainLoop()
mainloop.run()
joost
fuente
Si quiero llamar a otro método dbus diferente dentro del filtro de notificaciones, no funciona. Todo lo que consigo unable to connect to session bus: Operation was cancelled. Estamos pasando busal filtro.
Khurshid Alam
1
En mi instalación de Python (Python 3, Ubuntu) necesitaba from gi.repository import GLib as glibhacer que esto funcionara.
Owen
6

Por notificaciones, se refiere a las "burbujas de OSD" que envía algún software, como cambiar el volumen, chat de mensajería instantánea, etc. ¿Quieres crear un programa de Python para capturarlos?

Bueno, Ask Ubuntu no es el control de calidad de un programador, y el desarrollo de software está un poco más allá del alcance, pero aquí hay un pequeño código que capturé burbujas de notificación:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def notifications(bus, message):
    if message.get_member() == "Notify":
        print [arg for arg in message.get_args_list()]

DBusGMainLoop(set_as_default=True)

bus = dbus.SessionBus()
bus.add_match_string_non_blocking("interface='org.freedesktop.Notifications'")
bus.add_message_filter(notifications)

mainloop = glib.MainLoop()
mainloop.run()

Deje esto ejecutándose en una terminal, luego abra otra ventana de terminal y pruébelo:

notify-send --icon=/usr/share/pixmaps/debian-logo.png "My Title" "Some text body"

Y el programa generará esto:

[dbus.String(u'notify-send'), dbus.UInt32(0L), dbus.String(u'/usr/share/pixmaps/debian-logo.png'), dbus.String(u'My Title'), dbus.String(u'Some text body'),...

Como habrás adivinado, message.get_args_list()[0]es el remitente, [2] para el icono, [3] para el resumen y [4] para el texto del cuerpo.

Para conocer el significado de los otros campos, consulte los documentos de especificaciones oficiales

MestreLion
fuente
Parece que ya no funciona en algún momento el 16.04 o antes. La respuesta de Joost a continuación lo soluciona.
Catskul
3

Tuve problemas para lograr que alguno de los otros ejemplos funcionara, pero al final llegué allí. Aquí hay un ejemplo de trabajo:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def print_notification(bus, message):
  keys = ["app_name", "replaces_id", "app_icon", "summary",
          "body", "actions", "hints", "expire_timeout"]
  args = message.get_args_list()
  if len(args) == 8:
    notification = dict([(keys[i], args[i]) for i in range(8)])
    print notification["summary"], notification["body"]

loop = DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
session_bus.add_match_string("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop=true")
session_bus.add_message_filter(print_notification)

glib.MainLoop().run()

Si desea ver un ejemplo de trabajo más detallado, le recomiendo que consulte Notificaciones.py en el proyecto de notificaciones recientes .

kzar
fuente