Słuchanie przychodzących powiadomień libnotify za pomocą DBus

9

Próbuję filtrować każde powiadomienie przez espeak. Jednak nie mogę znaleźć sposobu na uzyskanie treści powiadomienia ze skryptu Pythona, a nawet jakiej nazwy sygnału należy słuchać.

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

Próba znalezienia go w Google wydaje się przynosić wyniki obejmujące tworzenie nowych powiadomień, więc teraz jestem całkowicie zagubiony.

Czy ktoś może mi w tym pomóc?

Krótko mówiąc, chcę nasłuchiwać przychodzących powiadomień za pomocą Pythona i uzyskiwać atrybut „body” powiadomienia.

manmachine
źródło
1
Wygląda na to, że powiadomienie nie generuje sygnału, tzn. dbus-monitor "type='signal',interface='org.freedesktop.Notifications'"Pokazuje tylko dbus-monitor "interface='org.freedesktop.Notifications'"powiadomienia (typ to „method_call”, a nie „signal”).
jfs

Odpowiedzi:

11

Aby zachować to na bieżąco: od dbus 1.5. Wymagany jest dodatkowy parametr podczas dodawania ciągu dopasowania, bus.add_match_string_non_blockingaby upewnić się, że otrzymamy wszystko.

Wynikowy kod wyglądałby następująco:

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
źródło
Jeśli chcę wywołać inną metodę dbus w filtrze powiadomień, to nie działa. Wszystko co dostaję unable to connect to session bus: Operation was cancelled. Przechodzimy busdo filtra.
Khurshid Alam
1
Podczas mojej instalacji w Pythonie (Python 3, Ubuntu) musiałem from gi.repository import GLib as glibto zrobić.
Owen
6

Przez powiadomienia rozumiesz „bąbelki OSD”, które wysyła niektóre oprogramowanie, takie jak zmiana głośności, czat itp.? Chcesz stworzyć program pythonowy do przechwytywania ich?

Cóż, Ask Ubuntu nie jest programistą, a programowanie jest nieco poza zakresem, ale oto mały kod, który przechwyciłem bańki powiadomień:

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

Pozostaw to uruchomione w terminalu, a następnie otwórz inne okno terminala i przetestuj:

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

A program wyświetli to:

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

Jak można się domyślać, message.get_args_list()[0]jest to nadawca, [2] dla ikony, [3] dla streszczenia i [4] dla tekstu podstawowego.

Znaczenie innych pól można znaleźć w oficjalnej dokumentacji specyfikacji

MestreLion
źródło
Wygląda na to, że nie działa już od 16.04. Poniższa odpowiedź Joosta naprawia to.
Catskul
3

Miałem problem z uruchomieniem któregokolwiek z innych przykładów, ale w końcu dotarłem. Oto działający przykład:

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

Jeśli chcesz zobaczyć bardziej szczegółowy przykład działania, polecam przejrzenie Notifications.py w najnowszym projekcie powiadomień .

kzar
źródło