initial commit
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[codz]
|
||||
@@ -205,3 +206,7 @@ cython_debug/
|
||||
marimo/_static/
|
||||
marimo/_lsp/
|
||||
__marimo__/
|
||||
=======
|
||||
config.ini
|
||||
/.claude/
|
||||
>>>>>>> f6afbf2 (initial commit)
|
||||
|
||||
231
README.md
Normal file
231
README.md
Normal file
@@ -0,0 +1,231 @@
|
||||
# GNOME Notification Forwarder
|
||||
|
||||
Forward all GNOME desktop notifications to Bark or Gotify.
|
||||
|
||||
## Features
|
||||
|
||||
- Monitors all GNOME desktop notifications in real-time
|
||||
- Forwards notifications to Bark API or Gotify automatically
|
||||
- Support for multiple notification services (Bark, Gotify, or both)
|
||||
- Includes application name in forwarded messages
|
||||
- Runs as a systemd service for automatic startup
|
||||
- Comprehensive logging
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Linux with GNOME desktop environment
|
||||
- Python 3.6+
|
||||
- D-Bus (pre-installed on most GNOME systems)
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Install Python dependencies
|
||||
|
||||
```bash
|
||||
# Install system dependencies
|
||||
sudo pacman -S python-dbus python-gobject python-requests
|
||||
|
||||
# OR using pip (if not using Arch)
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2. Make the script executable
|
||||
|
||||
```bash
|
||||
chmod +x notify_forwarder.py
|
||||
```
|
||||
|
||||
### 3. Test the script
|
||||
|
||||
```bash
|
||||
./notify_forwarder.py
|
||||
```
|
||||
|
||||
Then send a test notification:
|
||||
```bash
|
||||
notify-send "Test Title" "Test message body"
|
||||
```
|
||||
|
||||
You should see the notification forwarded to your Bark app and logged in the terminal.
|
||||
|
||||
## Running as a Service
|
||||
|
||||
### Set up systemd user service
|
||||
|
||||
1. Create the systemd user directory if it doesn't exist:
|
||||
```bash
|
||||
mkdir -p ~/.config/systemd/user
|
||||
```
|
||||
|
||||
2. Copy the service file:
|
||||
```bash
|
||||
cp notify-forwarder.service ~/.config/systemd/user/
|
||||
```
|
||||
|
||||
3. Reload systemd:
|
||||
```bash
|
||||
systemctl --user daemon-reload
|
||||
```
|
||||
|
||||
4. Enable and start the service:
|
||||
```bash
|
||||
systemctl --user enable notify-forwarder.service
|
||||
systemctl --user start notify-forwarder.service
|
||||
```
|
||||
|
||||
5. Check the service status:
|
||||
```bash
|
||||
systemctl --user status notify-forwarder.service
|
||||
```
|
||||
|
||||
6. View logs:
|
||||
```bash
|
||||
journalctl --user -u notify-forwarder.service -f
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is done via environment variables in your `~/.zshrc` file.
|
||||
|
||||
### Choose Notification Service
|
||||
|
||||
Set the `NOTIFICATION_SERVICE` variable to control which service(s) to use:
|
||||
|
||||
```bash
|
||||
# Options: bark, gotify, or both (default: bark)
|
||||
export NOTIFICATION_SERVICE="bark"
|
||||
```
|
||||
|
||||
### Configure Bark
|
||||
|
||||
If using Bark (default), add the following to your `~/.zshrc`:
|
||||
|
||||
```bash
|
||||
export BARK_URL="https://api.day.app/YOUR_BARK_KEY"
|
||||
```
|
||||
|
||||
### Configure Gotify
|
||||
|
||||
If using Gotify, add the following to your `~/.zshrc`:
|
||||
|
||||
```bash
|
||||
export GOTIFY_URL="https://gotify.example.com"
|
||||
export GOTIFY_TOKEN="your_gotify_app_token"
|
||||
```
|
||||
|
||||
### Use Both Services
|
||||
|
||||
To forward notifications to both Bark and Gotify simultaneously:
|
||||
|
||||
```bash
|
||||
export NOTIFICATION_SERVICE="both"
|
||||
export BARK_URL="https://api.day.app/YOUR_BARK_KEY"
|
||||
export GOTIFY_URL="https://gotify.example.com"
|
||||
export GOTIFY_TOKEN="your_gotify_app_token"
|
||||
```
|
||||
|
||||
### Apply Configuration
|
||||
|
||||
After editing `~/.zshrc`, reload it:
|
||||
|
||||
```bash
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
Then restart the service if it's already running:
|
||||
|
||||
```bash
|
||||
systemctl --user restart notify-forwarder.service
|
||||
```
|
||||
|
||||
## Stopping the Service
|
||||
|
||||
```bash
|
||||
# Stop the service
|
||||
systemctl --user stop notify-forwarder.service
|
||||
|
||||
# Disable auto-start
|
||||
systemctl --user disable notify-forwarder.service
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No notifications being forwarded
|
||||
|
||||
1. Check if the service is running:
|
||||
```bash
|
||||
systemctl --user status notify-forwarder.service
|
||||
```
|
||||
|
||||
2. Check the logs:
|
||||
```bash
|
||||
journalctl --user -u notify-forwarder.service -n 50
|
||||
```
|
||||
|
||||
3. Test your notification service manually:
|
||||
|
||||
For Bark:
|
||||
```bash
|
||||
curl "https://api.day.app/YOUR_BARK_KEY/Test/Message"
|
||||
```
|
||||
|
||||
For Gotify:
|
||||
```bash
|
||||
curl -X POST "https://gotify.example.com/message?token=YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title":"Test","message":"Test message","priority":5}'
|
||||
```
|
||||
|
||||
### Permission issues
|
||||
|
||||
Make sure the script has execute permissions:
|
||||
```bash
|
||||
chmod +x notify_forwarder.py
|
||||
```
|
||||
|
||||
### D-Bus connection issues
|
||||
|
||||
Ensure you're running the service as a user service (not system service), as it needs access to your user's D-Bus session.
|
||||
|
||||
## Uninstallation
|
||||
|
||||
```bash
|
||||
# Stop and disable the service
|
||||
systemctl --user stop notify-forwarder.service
|
||||
systemctl --user disable notify-forwarder.service
|
||||
|
||||
# Remove the service file
|
||||
rm ~/.config/systemd/user/notify-forwarder.service
|
||||
|
||||
# Reload systemd
|
||||
systemctl --user daemon-reload
|
||||
|
||||
# Remove the project directory
|
||||
rm -rf /home/lostecho/Documents/notify-forwarder
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 lostecho
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
See the [LICENSE](LICENSE) file for details.
|
||||
42
install.sh
Executable file
42
install.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
# Installation script for GNOME Notification Forwarder
|
||||
|
||||
set -e
|
||||
|
||||
echo "Installing GNOME Notification Forwarder to Bark..."
|
||||
echo
|
||||
|
||||
# Make the main script executable
|
||||
chmod +x notify_forwarder.py
|
||||
echo "✓ Made notify_forwarder.py executable"
|
||||
|
||||
# Create systemd user directory
|
||||
mkdir -p ~/.config/systemd/user
|
||||
echo "✓ Created systemd user directory"
|
||||
|
||||
# Copy service file
|
||||
cp notify-forwarder.service ~/.config/systemd/user/
|
||||
echo "✓ Copied service file to ~/.config/systemd/user/"
|
||||
|
||||
# Reload systemd
|
||||
systemctl --user daemon-reload
|
||||
echo "✓ Reloaded systemd"
|
||||
|
||||
echo
|
||||
echo "Installation complete!"
|
||||
echo
|
||||
echo "Next steps:"
|
||||
echo "1. Install dependencies:"
|
||||
echo " sudo pacman -S python-dbus python-gobject python-requests"
|
||||
echo
|
||||
echo "2. Start the service:"
|
||||
echo " systemctl --user start notify-forwarder.service"
|
||||
echo
|
||||
echo "3. Enable auto-start on login:"
|
||||
echo " systemctl --user enable notify-forwarder.service"
|
||||
echo
|
||||
echo "4. Check status:"
|
||||
echo " systemctl --user status notify-forwarder.service"
|
||||
echo
|
||||
echo "5. View logs:"
|
||||
echo " journalctl --user -u notify-forwarder.service -f"
|
||||
12
notify-forwarder.service
Normal file
12
notify-forwarder.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=GNOME Notification Forwarder to Bark
|
||||
After=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 %h/Documents/notify-forwarder/notify_forwarder.py
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
342
notify_forwarder.py
Executable file
342
notify_forwarder.py
Executable file
@@ -0,0 +1,342 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
GNOME Notification Forwarder to Bark
|
||||
Monitors GNOME desktop notifications and forwards them to Bark API
|
||||
"""
|
||||
|
||||
import dbus
|
||||
import dbus.mainloop.glib
|
||||
from gi.repository import GLib
|
||||
import requests
|
||||
import urllib.parse
|
||||
import logging
|
||||
from threading import Thread
|
||||
import hashlib
|
||||
import time
|
||||
from collections import deque
|
||||
import os
|
||||
import sys
|
||||
import configparser
|
||||
from pathlib import Path
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Configuration file path
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
CONFIG_FILE = SCRIPT_DIR / 'config.ini'
|
||||
|
||||
# Read configuration
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
if CONFIG_FILE.exists():
|
||||
logger.info(f"Loading configuration from {CONFIG_FILE}")
|
||||
config.read(CONFIG_FILE)
|
||||
|
||||
# Notification service configuration
|
||||
NOTIFICATION_SERVICE = config.get('notification', 'service', fallback='bark').lower()
|
||||
|
||||
# Bark API configuration
|
||||
BARK_URL = config.get('bark', 'url', fallback=None)
|
||||
|
||||
# Gotify configuration
|
||||
GOTIFY_URL = config.get('gotify', 'url', fallback=None)
|
||||
GOTIFY_TOKEN = config.get('gotify', 'token', fallback=None)
|
||||
|
||||
# Ntfy configuration
|
||||
NTFY_SERVER = config.get('ntfy', 'server', fallback='https://ntfy.sh')
|
||||
NTFY_TOPIC = config.get('ntfy', 'topic', fallback=None)
|
||||
else:
|
||||
# Fallback to environment variables if config file doesn't exist
|
||||
logger.warning(f"Config file not found at {CONFIG_FILE}, falling back to environment variables")
|
||||
NOTIFICATION_SERVICE = os.environ.get('NOTIFICATION_SERVICE', 'bark').lower()
|
||||
BARK_URL = os.environ.get('BARK_URL')
|
||||
GOTIFY_URL = os.environ.get('GOTIFY_URL')
|
||||
GOTIFY_TOKEN = os.environ.get('GOTIFY_TOKEN')
|
||||
NTFY_SERVER = os.environ.get('NTFY_SERVER', 'https://ntfy.sh')
|
||||
NTFY_TOPIC = os.environ.get('NTFY_TOPIC')
|
||||
|
||||
# Parse notification services (support comma-separated or 'all')
|
||||
if NOTIFICATION_SERVICE == 'all':
|
||||
ENABLED_SERVICES = ['bark', 'gotify', 'ntfy']
|
||||
else:
|
||||
ENABLED_SERVICES = [s.strip() for s in NOTIFICATION_SERVICE.split(',')]
|
||||
|
||||
# Validate configuration based on enabled services
|
||||
if 'bark' in ENABLED_SERVICES:
|
||||
if not BARK_URL:
|
||||
logger.error("Error: BARK_URL is not configured!")
|
||||
logger.error(f"Please set 'url' in the [bark] section of {CONFIG_FILE}")
|
||||
logger.error("Or set the BARK_URL environment variable")
|
||||
sys.exit(1)
|
||||
|
||||
if 'gotify' in ENABLED_SERVICES:
|
||||
if not GOTIFY_URL or not GOTIFY_TOKEN:
|
||||
logger.error("Error: Gotify URL and TOKEN are not configured!")
|
||||
logger.error(f"Please set 'url' and 'token' in the [gotify] section of {CONFIG_FILE}")
|
||||
logger.error("Or set the GOTIFY_URL and GOTIFY_TOKEN environment variables")
|
||||
sys.exit(1)
|
||||
|
||||
if 'ntfy' in ENABLED_SERVICES:
|
||||
if not NTFY_TOPIC:
|
||||
logger.error("Error: Ntfy TOPIC is not configured!")
|
||||
logger.error(f"Please set 'topic' in the [ntfy] section of {CONFIG_FILE}")
|
||||
logger.error("Or set the NTFY_TOPIC environment variable")
|
||||
sys.exit(1)
|
||||
|
||||
# Validate that at least one valid service is configured
|
||||
valid_services = {'bark', 'gotify', 'ntfy'}
|
||||
if not any(s in valid_services for s in ENABLED_SERVICES):
|
||||
logger.error(f"Error: Invalid NOTIFICATION_SERVICE '{NOTIFICATION_SERVICE}'")
|
||||
logger.error("Valid options are: bark, gotify, ntfy, or combinations like 'bark,gotify' or 'all'")
|
||||
sys.exit(1)
|
||||
|
||||
# Deduplication cache - stores hashes of recent notifications
|
||||
# Format: (hash, timestamp)
|
||||
recent_notifications = deque(maxlen=100)
|
||||
|
||||
|
||||
def send_to_bark(title, body, app_name=""):
|
||||
"""
|
||||
Send notification to Bark API (runs in separate thread to avoid blocking)
|
||||
|
||||
Args:
|
||||
title: Notification title
|
||||
body: Notification body
|
||||
app_name: Application name that triggered the notification
|
||||
"""
|
||||
try:
|
||||
# Construct message
|
||||
if app_name:
|
||||
message = f"[{app_name}] {body}" if body else f"[{app_name}]"
|
||||
else:
|
||||
message = body or "Notification"
|
||||
|
||||
# URL encode the parameters
|
||||
title_encoded = urllib.parse.quote(title or "Notification")
|
||||
message_encoded = urllib.parse.quote(message)
|
||||
|
||||
# Construct full URL
|
||||
url = f"{BARK_URL}/{title_encoded}/{message_encoded}"
|
||||
|
||||
# Send request with timeout
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info(f"✓ [Bark] Forwarded: {title} - {message[:50]}...")
|
||||
else:
|
||||
logger.error(f"✗ [Bark] Failed to forward notification. Status: {response.status_code}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"✗ [Bark] Network error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ [Bark] Error sending: {e}")
|
||||
|
||||
|
||||
def send_to_gotify(title, body, app_name=""):
|
||||
"""
|
||||
Send notification to Gotify API (runs in separate thread to avoid blocking)
|
||||
|
||||
Args:
|
||||
title: Notification title
|
||||
body: Notification body
|
||||
app_name: Application name that triggered the notification
|
||||
"""
|
||||
try:
|
||||
# Construct message
|
||||
if app_name:
|
||||
message = f"[{app_name}] {body}" if body else f"[{app_name}]"
|
||||
else:
|
||||
message = body or "Notification"
|
||||
|
||||
# Prepare Gotify message
|
||||
url = f"{GOTIFY_URL}/message"
|
||||
params = {'token': GOTIFY_TOKEN}
|
||||
data = {
|
||||
'title': title or "Notification",
|
||||
'message': message,
|
||||
'priority': 5
|
||||
}
|
||||
|
||||
# Send request with timeout
|
||||
response = requests.post(url, params=params, json=data, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info(f"✓ [Gotify] Forwarded: {title} - {message[:50]}...")
|
||||
else:
|
||||
logger.error(f"✗ [Gotify] Failed to forward notification. Status: {response.status_code}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"✗ [Gotify] Network error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ [Gotify] Error sending: {e}")
|
||||
|
||||
|
||||
def send_to_ntfy(title, body, app_name=""):
|
||||
"""
|
||||
Send notification to Ntfy (runs in separate thread to avoid blocking)
|
||||
|
||||
Args:
|
||||
title: Notification title
|
||||
body: Notification body
|
||||
app_name: Application name that triggered the notification
|
||||
"""
|
||||
try:
|
||||
# Construct message
|
||||
if app_name:
|
||||
message = f"[{app_name}] {body}" if body else f"[{app_name}]"
|
||||
else:
|
||||
message = body or "Notification"
|
||||
|
||||
# Prepare Ntfy request
|
||||
url = f"{NTFY_SERVER}/{NTFY_TOPIC}"
|
||||
headers = {
|
||||
'Title': title or "Notification",
|
||||
'Priority': '3',
|
||||
'Tags': 'computer'
|
||||
}
|
||||
|
||||
# Send request with timeout
|
||||
response = requests.post(url, data=message.encode('utf-8'), headers=headers, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info(f"✓ [Ntfy] Forwarded: {title} - {message[:50]}...")
|
||||
else:
|
||||
logger.error(f"✗ [Ntfy] Failed to forward notification. Status: {response.status_code}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"✗ [Ntfy] Network error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ [Ntfy] Error sending: {e}")
|
||||
|
||||
|
||||
def message_filter(bus, message):
|
||||
"""
|
||||
Filter and handle D-Bus messages
|
||||
"""
|
||||
try:
|
||||
# Check if this is a method call to Notify
|
||||
if message.get_member() != "Notify":
|
||||
return
|
||||
|
||||
if message.get_interface() != "org.freedesktop.Notifications":
|
||||
return
|
||||
|
||||
# Get the arguments
|
||||
args = message.get_args_list()
|
||||
if len(args) < 5:
|
||||
return
|
||||
|
||||
app_name = str(args[0])
|
||||
replaces_id = args[1]
|
||||
app_icon = args[2]
|
||||
summary = str(args[3])
|
||||
body = str(args[4])
|
||||
|
||||
# Skip empty notifications
|
||||
if not summary and not body:
|
||||
return
|
||||
|
||||
# Create a hash of the notification for deduplication
|
||||
notification_str = f"{app_name}:{summary}:{body}"
|
||||
notification_hash = hashlib.md5(notification_str.encode()).hexdigest()
|
||||
current_time = time.time()
|
||||
|
||||
# Check if this notification was recently processed (within 2 seconds)
|
||||
for cached_hash, cached_time in recent_notifications:
|
||||
if cached_hash == notification_hash and (current_time - cached_time) < 2:
|
||||
# Duplicate notification, skip it
|
||||
return
|
||||
|
||||
# Add to cache
|
||||
recent_notifications.append((notification_hash, current_time))
|
||||
|
||||
# Log the notification
|
||||
logger.info(f"Received: [{app_name}] {summary}")
|
||||
|
||||
# Forward to notification service(s) in separate thread(s) to avoid blocking
|
||||
if 'bark' in ENABLED_SERVICES:
|
||||
thread = Thread(target=send_to_bark, args=(summary, body, app_name))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
if 'gotify' in ENABLED_SERVICES:
|
||||
thread = Thread(target=send_to_gotify, args=(summary, body, app_name))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
if 'ntfy' in ENABLED_SERVICES:
|
||||
thread = Thread(target=send_to_ntfy, args=(summary, body, app_name))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error handling message: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function to set up D-Bus monitoring
|
||||
"""
|
||||
logger.info("Starting GNOME Notification Forwarder...")
|
||||
logger.info(f"Enabled services: {', '.join(ENABLED_SERVICES)}")
|
||||
|
||||
if 'bark' in ENABLED_SERVICES:
|
||||
logger.info(f"Bark URL: {BARK_URL}")
|
||||
|
||||
if 'gotify' in ENABLED_SERVICES:
|
||||
logger.info(f"Gotify URL: {GOTIFY_URL}")
|
||||
|
||||
if 'ntfy' in ENABLED_SERVICES:
|
||||
logger.info(f"Ntfy server: {NTFY_SERVER}")
|
||||
logger.info(f"Ntfy topic: {NTFY_TOPIC}")
|
||||
|
||||
try:
|
||||
# Set up D-Bus main loop
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
# Get session bus
|
||||
bus = dbus.SessionBus()
|
||||
|
||||
# Become a monitor to intercept messages
|
||||
bus.call_blocking(
|
||||
'org.freedesktop.DBus',
|
||||
'/org/freedesktop/DBus',
|
||||
'org.freedesktop.DBus.Monitoring',
|
||||
'BecomeMonitor',
|
||||
'asu',
|
||||
([
|
||||
"type='method_call',interface='org.freedesktop.Notifications',member='Notify'"
|
||||
], 0)
|
||||
)
|
||||
|
||||
# Add message filter
|
||||
bus.add_message_filter(message_filter)
|
||||
|
||||
logger.info("✓ Monitoring notifications... Press Ctrl+C to stop.")
|
||||
|
||||
# Run main loop
|
||||
loop = GLib.MainLoop()
|
||||
loop.run()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("\nStopping notification forwarder...")
|
||||
except dbus.exceptions.DBusException as e:
|
||||
if "org.freedesktop.DBus.Monitoring" in str(e):
|
||||
logger.error("Error: Unable to become D-Bus monitor.")
|
||||
logger.error("This might require additional permissions or a policy update.")
|
||||
logger.error("Try running with: dbus-send or check D-Bus policies.")
|
||||
else:
|
||||
logger.error(f"D-Bus error: {e}")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Fatal error: {e}")
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
dbus-python>=1.2.18
|
||||
PyGObject>=3.42.0
|
||||
requests>=2.28.0
|
||||
Reference in New Issue
Block a user