Abhören eingehender libnotify-Benachrichtigungen mit DBus

9

Ich versuche, jede Benachrichtigung durch espeak zu filtern. Ich kann jedoch anscheinend keine Möglichkeit finden, den Benachrichtigungstext aus einem Python-Skript abzurufen oder sogar zu erfahren, welchen Signalnamen ich abhören soll.

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

Der Versuch, dafür zu googeln, scheint nur zu Ergebnissen zu führen, bei denen neue Benachrichtigungen erstellt werden. Daher bin ich jetzt völlig verloren.

Kann mir jemand dabei helfen?

Kurz gesagt, ich möchte mit Python auf eingehende Benachrichtigungen warten und das Attribut "body" der Benachrichtigung erhalten.

manmachine
quelle
1
Es scheint, dass eine Benachrichtigung kein Signal erzeugt, dh dbus-monitor "type='signal',interface='org.freedesktop.Notifications'"nichts anzeigt, aber dbus-monitor "interface='org.freedesktop.Notifications'"Benachrichtigungen anzeigt (Typ ist 'method_call', nicht 'signal').
JFS

Antworten:

11

Um dies auf dem neuesten Stand zu halten: Ab dbus 1.5 ist beim Hinzufügen einer Übereinstimmungszeichenfolge mit ein zusätzlicher Parameter erforderlich bus.add_match_string_non_blocking, um sicherzustellen, dass wir alles erhalten.

Der resultierende Code wäre der folgende:

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
quelle
Wenn ich eine andere dbus-Methode im Benachrichtigungsfilter aufrufen möchte, funktioniert dies nicht. Alles was ich bekomme unable to connect to session bus: Operation was cancelled. Wir gehen buszum Filter.
Khurshid Alam
Bei meiner Python-Installation (Python 3, Ubuntu) musste from gi.repository import GLib as glibdies funktionieren.
Owen
6

Mit Benachrichtigungen meinen Sie die "OSD-Blasen", die einige Software sendet, wie z. B. Ändern der Lautstärke, IM-Chat usw.? Sie möchten ein Python-Programm erstellen, um diese zu erfassen?

Nun, Ask Ubuntu ist keine Qualitätssicherung für Programmierer, und die Softwareentwicklung geht etwas über den Rahmen hinaus, aber hier ist ein kleiner Code, mit dem ich Benachrichtigungsblasen erfasst habe:

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

Lassen Sie dies in einem Terminal laufen, öffnen Sie dann ein anderes Terminalfenster und testen Sie es:

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

Und das Programm gibt Folgendes aus:

[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'),...

Wie Sie vielleicht erraten haben, message.get_args_list()[0]ist der Absender [2] für das Symbol, [3] für die Zusammenfassung und [4] für den Textkörper.

Informationen zur Bedeutung der anderen Felder finden Sie in den offiziellen Spezifikationsdokumenten

MestreLion
quelle
Es sieht so aus, als ob es ab dem 16.04. Nicht mehr funktioniert. Die Antwort von Joost unten behebt das Problem.
Catskul
3

Ich hatte Probleme, eines der anderen Beispiele tatsächlich zum Laufen zu bringen, aber am Ende bin ich dort angekommen. Hier ist ein Arbeitsbeispiel:

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

Wenn Sie ein detaillierteres Arbeitsbeispiel sehen möchten, empfehlen wir Ihnen, sich Notifications.py im Projekt Recent_notifications anzusehen .

kzar
quelle