Чтение уведомлений на рабочем столе из командной строки. Дебиан/УбунтуPython

Программы на Python
Ответить
Anonymous
 Чтение уведомлений на рабочем столе из командной строки. Дебиан/Убунту

Сообщение Anonymous »

Запуск Ubuntu 24.04lts.

Я пытаюсь создать сценарий, который прослушивает dbus уведомлений рабочего стола и выводит отправителя и сообщение в командную строку.... конечная цель - запустить определенную функцию, когда я получаю определенное уведомление.
Я пробовал использовать dbus-monitor --session, который распечатывает данные, когда я получаю уведомление, но я не вижу фактического уведомления. Я попросил Gemini AI написать код на Python, этот код работает, но когда я получаю уведомление, ничего не происходит.

Код: Выделить всё

import asyncio

Код: Выделить всё

from dbus_next.aio import MessageBus

Код: Выделить всё

from dbus_next.constants import BusType, MessageType

Код: Выделить всё

from dbus_next import Message, Variant

Код: Выделить всё

import logging

Код: Выделить всё

# Set up basic logging

Код: Выделить всё

# Note: We are only using INFO level for connection status, 

Код: Выделить всё

# message processing is handled via print() for clarity.

Код: Выделить всё

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

Код: Выделить всё

# --- DBus Interface Constants ---

Код: Выделить всё

# The D-Bus service name for notifications

Код: Выделить всё

NOTIF_SERVICE = 'org.freedesktop.Notifications'

Код: Выделить всё

# The D-Bus object path for notifications

Код: Выделить всё

NOTIF_PATH = '/org/freedesktop/Notifications'

Код: Выделить всё

# The D-Bus interface for notifications

Код: Выделить всё

NOTIF_INTERFACE = NOTIF_SERVICE

Код: Выделить всё

# ANSI escape codes for bold text

Код: Выделить всё

BOLD_START = '\033[1m'

Код: Выделить всё

BOLD_END = '\033[0m'

Код: Выделить всё

def message_handler(message):

Код: Выделить всё

   Generic handler for D-Bus messages, focusing only on new notifications

Код: Выделить всё

    (Notify method calls) and printing the sender, summary, and message body.

Код: Выделить всё

    if message.interface == NOTIF_INTERFACE:

Код: Выделить всё

        # --- Handle New Notification (Method Call) ---

Код: Выделить всё

        if message.message_type == MessageType.METHOD_CALL and message.member == 'Notify':

Код: Выделить всё

            # Notify arguments: (app_name, replaces_id, app_icon, summary, body, actions, hints, expire_timeout)

Код: Выделить всё

            # Ensure we have enough arguments (at least app_name and body)

Код: Выделить всё

            if len(message.body) >= 8:

Код: Выделить всё

                app_name = message.body[0] # App Name (Sender)

Код: Выделить всё

                summary = message.body[3] # Notification Summary (Title)

Код: Выделить всё

                body_text = message.body[4] # Notification Body (Main message)

Код: Выделить всё

                # Combine summary and body for the message

Код: Выделить всё

                # If both exist, use "Summary: Body". If only one exists, use that.

Код: Выделить всё

                if summary and body_text:

Код: Выделить всё

                    message_content = f"{summary}: {body_text}"

Код: Выделить всё

                elif summary:

Код: Выделить всё

                    message_content = summary

Код: Выделить всё

                    message_content = body_text

Код: Выделить всё

                output = f"[{app_name}] {message_content}"

Код: Выделить всё

                # Apply bold formatting if the sender is Discord (case-insensitive check)

Код: Выделить всё

                if app_name.lower() == 'discord':

Код: Выделить всё

                    output = f"{BOLD_START}{output}{BOLD_END}"

Код: Выделить всё

                print(output)

Код: Выделить всё

        # Log other relevant messages (like replies to GetCapabilities)

Код: Выделить всё

            logging.debug(f"[D-Bus Message] Type: {message.message_type.name}, Member: {message.member}, Body: {message.body}")

Код: Выделить всё

async def notification_listener(bus):

Код: Выделить всё

   Configures the bus to listen for all messages related to the

Код: Выделить всё

    org.freedesktop.Notifications interface.

Код: Выделить всё

    # 1. Add the generic message handler

Код: Выделить всё

    bus.add_message_handler(message_handler)

Код: Выделить всё

    # 2.  Use AddMatch to filter messages directed to this interface

Код: Выделить всё

    # This is crucial for catching the 'Notify' method call.

Код: Выделить всё

   # The rule is updated to match on the specific method call ('Notify') rather than

Код: Выделить всё

   # relying solely on the destination service, which is a more robust way to capture

Код: Выделить всё

    # new notification requests.

Код: Выделить всё

    match_rule = f"type='method_call', interface='{NOTIF_INTERFACE}', member='Notify'"

Код: Выделить всё

    await bus.call(

Код: Выделить всё

        Message(

Код: Выделить всё

            destination='org.freedesktop.DBus',

Код: Выделить всё

            path='/org/freedesktop/DBus',

Код: Выделить всё

            interface='org.freedesktop.DBus',

Код: Выделить всё

            member='AddMatch',

Код: Выделить всё

            signature='s',

Код: Выделить всё

            body=[match_rule]

Код: Выделить всё

    logging.info("Listening for ALL D-Bus Messages on org.freedesktop.Notifications interface.")

Код: Выделить всё

    logging.info("To test, send a notification, e.g., 'notify-send Hello World'")

Код: Выделить всё

    # Keep the asyncio loop running indefinitely

Код: Выделить всё

    await asyncio.get_running_loop().create_future()

Код: Выделить всё

async def main():

Код: Выделить всё

    The main entry point for the script.

Код: Выделить всё

        logging.info(f"Attempting to connect to the D-Bus session bus...")

Код: Выделить всё

        bus = await MessageBus(bus_type=BusType.SESSION).connect()

Код: Выделить всё

        logging.info("Successfully connected to the D-Bus session bus.")

Код: Выделить всё

        # Attempt to call the GetCapabilities method to ensure the service is running

Код: Выделить всё

        reply = await bus.call(

Код: Выделить всё

            Message(

Код: Выделить всё

                destination=NOTIF_SERVICE,

Код: Выделить всё

                path=NOTIF_PATH,

Код: Выделить всё

                interface=NOTIF_INTERFACE,

Код: Выделить всё

                member='GetCapabilities',

Код: Выделить всё

                signature='',

Код: Выделить всё

                body=[]

Код: Выделить всё

        if reply.message_type == MessageType.METHOD_RETURN:

Код: Выделить всё

            caps = reply.body[0]

Код: Выделить всё

            logging.info(f"Notification service capabilities retrieved: {caps}")

Код: Выделить всё

            await notification_listener(bus)

Код: Выделить всё

            # This often means no notification daemon (like dunst or a desktop environment's service) is running.

Код: Выделить всё

            logging.error("Could not retrieve notification service capabilities. Is a notification daemon running?")

Код: Выделить всё

    except Exception as e:

Код: Выделить всё

        logging.error(f"Error during D-Bus setup or initial capability check:   {e}")

Код: Выделить всё

if __name__ == "__main__":

Код: Выделить всё

        # Run the main coroutine

Код: Выделить всё

        asyncio.run(main())

Код: Выделить всё

    except KeyboardInterrupt:

Код: Выделить всё

        logging.info("Notification listener stopped by user.")

Код: Выделить всё

    except Exception as e:

Код: Выделить всё

        logging.error(f"An unexpected error occurred: {e}")
Похоже, что это должна быть простая задача... Если бы я мог, я бы предпочел использовать скрипт bash, но Python тоже подойдет.
Я нашел [это сообщение][1], в котором был скрипт Python, который мне пришлось обновить для работы с py3. Этот скрипт запускается, но ничего не происходит, когда я получаю уведомление или отправляю его через notify-send

Код: Выделить всё

import gi

Код: Выделить всё

gi.require_version("Gtk", "3.0") # or "4.0" depending on your target GTK version

Код: Выделить всё

from gi.repository import Gtk

Код: Выделить всё

import dbus

Код: Выделить всё

from dbus.mainloop.glib import DBusGMainLoop

Код: Выделить всё

def filter_cb(bus, message):

Код: Выделить всё

    # the NameAcquired message comes through before match string gets applied

Код: Выделить всё

    if message.get_member() != "Notify":

Код: Выделить всё

    args = message.get_args_list()

Код: Выделить всё

    # args are

Код: Выделить всё

    # (app_name, notification_id, icon, summary, body, actions, hints, timeout)

Код: Выделить всё

    print("Notification from app '%s'" % args[0])

Код: Выделить всё

    print("Summary: %s" % args[3])

Код: Выделить всё

    print("Body: %s", args[4])

Код: Выделить всё

DBusGMainLoop(set_as_default=True)

Код: Выделить всё

bus = dbus.SessionBus()

Код: Выделить всё

bus.add_match_string(

Код: Выделить всё

    "type='method_call',interface='org.freedesktop.Notifications',member='Notify'")

Код: Выделить всё

bus.add_message_filter(filter_cb)

Код: Выделить всё

Gtk.main()
Спасибо.
[1]: http://askubuntu.com/questions/38733/ho ... tor-output

Подробнее здесь: https://stackoverflow.com/questions/798 ... ian-ubuntu
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»