GuGa 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: GuGa
3
+ Version: 1.0.3
4
+ Summary: Linux to Android notification bridge.
5
+ Requires-Python: >=3.7
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: flask
8
+ Requires-Dist: flask-socketio
9
+ Requires-Dist: eventlet
10
+ Requires-Dist: gunicorn
11
+ Requires-Dist: python-dotenv
12
+ Requires-Dist: qrcode
13
+ Requires-Dist: cryptography
14
+ Requires-Dist: aiohttp
15
+
16
+ <p align="center">
17
+ <img src="https://raw.githubusercontent.com/PositiveMatician/GuGa-Nexus/main/app-stable/app/src/main/assets/logo.png" width="128" height="128" />
18
+ </p>
19
+
20
+ <h1 align="center">GuGa Nexus</h1>
21
+
22
+ <p align="center">
23
+ Send your Linux terminal and OS notifications straight to your Android.<br/>
24
+ No cloud. No subscription. No port forwarding.
25
+ </p>
26
+
27
+ <p align="center">
28
+ <a href="https://pypi.org/project/GuGa/">
29
+ <img src="https://img.shields.io/pypi/v/GuGa.svg" alt="PyPI Version" />
30
+ </a>
31
+ <img src="https://img.shields.io/badge/platform-Linux-lightgrey" alt="Platform" />
32
+ <img src="https://img.shields.io/badge/encryption-AES--256--GCM-green" alt="Encryption" />
33
+ <img src="https://img.shields.io/badge/license-MIT-yellow" alt="License" />
34
+ </p>
35
+
36
+ 🔗 [View the full Open Source Repository on GitHub](https://github.com/PositiveMatician/GuGa-Nexus)
37
+
38
+ ---
39
+
40
+ **GuGa Nexus** is a minimalist, privacy-focused ecosystem that bridges your Linux machine and your Android device. It uses end-to-end AES-256-GCM encryption and works strictly over your own local network or a direct Cloudflare Tunnel—never storing your data on a third-party server.
41
+
42
+ - **Waiting for a long script to finish?** Get notified the moment it's done.
43
+ - **Training a model overnight?** Wake up to the final accuracy line in your notification.
44
+ - **SSHed into a remote server?** GuGa reaches your phone over the internet seamlessly.
45
+
46
+ ---
47
+
48
+ ## Installation
49
+
50
+ GuGa is distributed strictly as a standard Python module via PyPI.
51
+
52
+ 1. **Install the package:**
53
+ ```bash
54
+ pip install GuGa
55
+ ```
56
+
57
+ 2. **Initialize the background daemon:**
58
+ ```bash
59
+ guga --install-service
60
+ ```
61
+ *(This interactive setup will cleanly provision your systemd daemon and configure your network routing. Afterwards, your QR code will be generated).*
62
+
63
+ 3. **Install the Android App:**
64
+ Download the `stable` Android APK from the [GitHub Releases Page](https://github.com/PositiveMatician/GuGa-Nexus/releases) and scan the QR code printed in your terminal!
65
+
66
+ ---
67
+
68
+ ## 🚀 Examples & Usage
69
+
70
+ Once deployed, the `guga` command-line utility is globally available on your terminal. It's designed to automatically detect whether you want to send a plain text notification, or if you want it to execute and watch a long-running process on your behalf.
71
+
72
+ ### 1. Plain Notifications (Message Mode)
73
+ Send simple text updates directly to your Android device.
74
+
75
+ ```bash
76
+ # Push a simple message
77
+ guga "Build finished successfully ✅"
78
+
79
+ # You can also stream output into it via stdin!
80
+ echo "Database migration complete" | guga
81
+ ```
82
+
83
+ ### 2. Process Watching (Run Mode)
84
+ Put `guga` in front of any command. It will execute the command natively while streaming the output to your terminal just as normal. Once the command finishes, it will instantly notify your phone with the **Elapsed Time**, **Exit Status**, and the **Last Console Line**.
85
+
86
+ ```bash
87
+ # Get notified when training finishes
88
+ guga python train_model.py --epochs 100
89
+
90
+ # Compile code and get notified if it succeeded or crashed
91
+ guga make build-project
92
+
93
+ # Add custom labels to your notifications for clarity
94
+ guga -r ./deploy.sh --title "Production Server"
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Post-Install Utilities
100
+
101
+ If you need to view your pairing credentials or manage your background daemon after installation, GuGa provides several utility commands:
102
+
103
+ ```bash
104
+ guga --qr # Show the pairing QR code
105
+ guga --show-pin # Show the secure Zero-Trust PIN
106
+ guga --install-service --reconfigure # Re-run the interactive setup
107
+ ```
108
+
109
+ To control the Linux backend server explicitly:
110
+ ```bash
111
+ sudo systemctl start guga # Start the server daemon
112
+ sudo systemctl stop guga # Stop the server daemon
113
+ journalctl -u guga -f # View live server connection logs
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Core Features & Architecture
119
+
120
+ * **Terminal Tracking:** Push notifications to Android via the `guga` global CLI.
121
+ * **System OS Monitoring:** Automatically intercepts DBus to forward your native Linux desktop notifications straight to your phone.
122
+ * **Zero-Trust Coupling:** Cryptographically secure pairing logic relying strictly on visual QR transmission + 8-Digit PINs (No OAuth or cloud-accounts required).
123
+ * **Network Versatility:** Operates flawlessly in **LAN-only mode** strictly over local WiFi, or seamlessly hooks into Cloudflared to grant you **Internet-anywhere access** without needing to own a domain or configure port-forwarding.
@@ -0,0 +1,20 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ GuGa.egg-info/PKG-INFO
6
+ GuGa.egg-info/SOURCES.txt
7
+ GuGa.egg-info/dependency_links.txt
8
+ GuGa.egg-info/entry_points.txt
9
+ GuGa.egg-info/requires.txt
10
+ GuGa.egg-info/top_level.txt
11
+ guga/__init__.py
12
+ guga/alerter.py
13
+ guga/cli.py
14
+ guga/daemon.py
15
+ guga/installer.py
16
+ guga/__pycache__/__init__.cpython-314.pyc
17
+ guga/__pycache__/cli.cpython-314.pyc
18
+ guga/__pycache__/daemon.cpython-314.pyc
19
+ guga/man/guga.1
20
+ guga/man/guga.md
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ guga = guga.cli:main
@@ -0,0 +1,8 @@
1
+ flask
2
+ flask-socketio
3
+ eventlet
4
+ gunicorn
5
+ python-dotenv
6
+ qrcode
7
+ cryptography
8
+ aiohttp
@@ -0,0 +1 @@
1
+ guga
guga-1.0.3/MANIFEST.in ADDED
@@ -0,0 +1,2 @@
1
+ recursive-include guga/man *
2
+ recursive-include guga *
guga-1.0.3/PKG-INFO ADDED
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: GuGa
3
+ Version: 1.0.3
4
+ Summary: Linux to Android notification bridge.
5
+ Requires-Python: >=3.7
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: flask
8
+ Requires-Dist: flask-socketio
9
+ Requires-Dist: eventlet
10
+ Requires-Dist: gunicorn
11
+ Requires-Dist: python-dotenv
12
+ Requires-Dist: qrcode
13
+ Requires-Dist: cryptography
14
+ Requires-Dist: aiohttp
15
+
16
+ <p align="center">
17
+ <img src="https://raw.githubusercontent.com/PositiveMatician/GuGa-Nexus/main/app-stable/app/src/main/assets/logo.png" width="128" height="128" />
18
+ </p>
19
+
20
+ <h1 align="center">GuGa Nexus</h1>
21
+
22
+ <p align="center">
23
+ Send your Linux terminal and OS notifications straight to your Android.<br/>
24
+ No cloud. No subscription. No port forwarding.
25
+ </p>
26
+
27
+ <p align="center">
28
+ <a href="https://pypi.org/project/GuGa/">
29
+ <img src="https://img.shields.io/pypi/v/GuGa.svg" alt="PyPI Version" />
30
+ </a>
31
+ <img src="https://img.shields.io/badge/platform-Linux-lightgrey" alt="Platform" />
32
+ <img src="https://img.shields.io/badge/encryption-AES--256--GCM-green" alt="Encryption" />
33
+ <img src="https://img.shields.io/badge/license-MIT-yellow" alt="License" />
34
+ </p>
35
+
36
+ 🔗 [View the full Open Source Repository on GitHub](https://github.com/PositiveMatician/GuGa-Nexus)
37
+
38
+ ---
39
+
40
+ **GuGa Nexus** is a minimalist, privacy-focused ecosystem that bridges your Linux machine and your Android device. It uses end-to-end AES-256-GCM encryption and works strictly over your own local network or a direct Cloudflare Tunnel—never storing your data on a third-party server.
41
+
42
+ - **Waiting for a long script to finish?** Get notified the moment it's done.
43
+ - **Training a model overnight?** Wake up to the final accuracy line in your notification.
44
+ - **SSHed into a remote server?** GuGa reaches your phone over the internet seamlessly.
45
+
46
+ ---
47
+
48
+ ## Installation
49
+
50
+ GuGa is distributed strictly as a standard Python module via PyPI.
51
+
52
+ 1. **Install the package:**
53
+ ```bash
54
+ pip install GuGa
55
+ ```
56
+
57
+ 2. **Initialize the background daemon:**
58
+ ```bash
59
+ guga --install-service
60
+ ```
61
+ *(This interactive setup will cleanly provision your systemd daemon and configure your network routing. Afterwards, your QR code will be generated).*
62
+
63
+ 3. **Install the Android App:**
64
+ Download the `stable` Android APK from the [GitHub Releases Page](https://github.com/PositiveMatician/GuGa-Nexus/releases) and scan the QR code printed in your terminal!
65
+
66
+ ---
67
+
68
+ ## 🚀 Examples & Usage
69
+
70
+ Once deployed, the `guga` command-line utility is globally available on your terminal. It's designed to automatically detect whether you want to send a plain text notification, or if you want it to execute and watch a long-running process on your behalf.
71
+
72
+ ### 1. Plain Notifications (Message Mode)
73
+ Send simple text updates directly to your Android device.
74
+
75
+ ```bash
76
+ # Push a simple message
77
+ guga "Build finished successfully ✅"
78
+
79
+ # You can also stream output into it via stdin!
80
+ echo "Database migration complete" | guga
81
+ ```
82
+
83
+ ### 2. Process Watching (Run Mode)
84
+ Put `guga` in front of any command. It will execute the command natively while streaming the output to your terminal just as normal. Once the command finishes, it will instantly notify your phone with the **Elapsed Time**, **Exit Status**, and the **Last Console Line**.
85
+
86
+ ```bash
87
+ # Get notified when training finishes
88
+ guga python train_model.py --epochs 100
89
+
90
+ # Compile code and get notified if it succeeded or crashed
91
+ guga make build-project
92
+
93
+ # Add custom labels to your notifications for clarity
94
+ guga -r ./deploy.sh --title "Production Server"
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Post-Install Utilities
100
+
101
+ If you need to view your pairing credentials or manage your background daemon after installation, GuGa provides several utility commands:
102
+
103
+ ```bash
104
+ guga --qr # Show the pairing QR code
105
+ guga --show-pin # Show the secure Zero-Trust PIN
106
+ guga --install-service --reconfigure # Re-run the interactive setup
107
+ ```
108
+
109
+ To control the Linux backend server explicitly:
110
+ ```bash
111
+ sudo systemctl start guga # Start the server daemon
112
+ sudo systemctl stop guga # Stop the server daemon
113
+ journalctl -u guga -f # View live server connection logs
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Core Features & Architecture
119
+
120
+ * **Terminal Tracking:** Push notifications to Android via the `guga` global CLI.
121
+ * **System OS Monitoring:** Automatically intercepts DBus to forward your native Linux desktop notifications straight to your phone.
122
+ * **Zero-Trust Coupling:** Cryptographically secure pairing logic relying strictly on visual QR transmission + 8-Digit PINs (No OAuth or cloud-accounts required).
123
+ * **Network Versatility:** Operates flawlessly in **LAN-only mode** strictly over local WiFi, or seamlessly hooks into Cloudflared to grant you **Internet-anywhere access** without needing to own a domain or configure port-forwarding.
guga-1.0.3/README.md ADDED
@@ -0,0 +1,108 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/PositiveMatician/GuGa-Nexus/main/app-stable/app/src/main/assets/logo.png" width="128" height="128" />
3
+ </p>
4
+
5
+ <h1 align="center">GuGa Nexus</h1>
6
+
7
+ <p align="center">
8
+ Send your Linux terminal and OS notifications straight to your Android.<br/>
9
+ No cloud. No subscription. No port forwarding.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://pypi.org/project/GuGa/">
14
+ <img src="https://img.shields.io/pypi/v/GuGa.svg" alt="PyPI Version" />
15
+ </a>
16
+ <img src="https://img.shields.io/badge/platform-Linux-lightgrey" alt="Platform" />
17
+ <img src="https://img.shields.io/badge/encryption-AES--256--GCM-green" alt="Encryption" />
18
+ <img src="https://img.shields.io/badge/license-MIT-yellow" alt="License" />
19
+ </p>
20
+
21
+ 🔗 [View the full Open Source Repository on GitHub](https://github.com/PositiveMatician/GuGa-Nexus)
22
+
23
+ ---
24
+
25
+ **GuGa Nexus** is a minimalist, privacy-focused ecosystem that bridges your Linux machine and your Android device. It uses end-to-end AES-256-GCM encryption and works strictly over your own local network or a direct Cloudflare Tunnel—never storing your data on a third-party server.
26
+
27
+ - **Waiting for a long script to finish?** Get notified the moment it's done.
28
+ - **Training a model overnight?** Wake up to the final accuracy line in your notification.
29
+ - **SSHed into a remote server?** GuGa reaches your phone over the internet seamlessly.
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ GuGa is distributed strictly as a standard Python module via PyPI.
36
+
37
+ 1. **Install the package:**
38
+ ```bash
39
+ pip install GuGa
40
+ ```
41
+
42
+ 2. **Initialize the background daemon:**
43
+ ```bash
44
+ guga --install-service
45
+ ```
46
+ *(This interactive setup will cleanly provision your systemd daemon and configure your network routing. Afterwards, your QR code will be generated).*
47
+
48
+ 3. **Install the Android App:**
49
+ Download the `stable` Android APK from the [GitHub Releases Page](https://github.com/PositiveMatician/GuGa-Nexus/releases) and scan the QR code printed in your terminal!
50
+
51
+ ---
52
+
53
+ ## 🚀 Examples & Usage
54
+
55
+ Once deployed, the `guga` command-line utility is globally available on your terminal. It's designed to automatically detect whether you want to send a plain text notification, or if you want it to execute and watch a long-running process on your behalf.
56
+
57
+ ### 1. Plain Notifications (Message Mode)
58
+ Send simple text updates directly to your Android device.
59
+
60
+ ```bash
61
+ # Push a simple message
62
+ guga "Build finished successfully ✅"
63
+
64
+ # You can also stream output into it via stdin!
65
+ echo "Database migration complete" | guga
66
+ ```
67
+
68
+ ### 2. Process Watching (Run Mode)
69
+ Put `guga` in front of any command. It will execute the command natively while streaming the output to your terminal just as normal. Once the command finishes, it will instantly notify your phone with the **Elapsed Time**, **Exit Status**, and the **Last Console Line**.
70
+
71
+ ```bash
72
+ # Get notified when training finishes
73
+ guga python train_model.py --epochs 100
74
+
75
+ # Compile code and get notified if it succeeded or crashed
76
+ guga make build-project
77
+
78
+ # Add custom labels to your notifications for clarity
79
+ guga -r ./deploy.sh --title "Production Server"
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Post-Install Utilities
85
+
86
+ If you need to view your pairing credentials or manage your background daemon after installation, GuGa provides several utility commands:
87
+
88
+ ```bash
89
+ guga --qr # Show the pairing QR code
90
+ guga --show-pin # Show the secure Zero-Trust PIN
91
+ guga --install-service --reconfigure # Re-run the interactive setup
92
+ ```
93
+
94
+ To control the Linux backend server explicitly:
95
+ ```bash
96
+ sudo systemctl start guga # Start the server daemon
97
+ sudo systemctl stop guga # Stop the server daemon
98
+ journalctl -u guga -f # View live server connection logs
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Core Features & Architecture
104
+
105
+ * **Terminal Tracking:** Push notifications to Android via the `guga` global CLI.
106
+ * **System OS Monitoring:** Automatically intercepts DBus to forward your native Linux desktop notifications straight to your phone.
107
+ * **Zero-Trust Coupling:** Cryptographically secure pairing logic relying strictly on visual QR transmission + 8-Digit PINs (No OAuth or cloud-accounts required).
108
+ * **Network Versatility:** Operates flawlessly in **LAN-only mode** strictly over local WiFi, or seamlessly hooks into Cloudflared to grant you **Internet-anywhere access** without needing to own a domain or configure port-forwarding.
File without changes
@@ -0,0 +1,174 @@
1
+ import asyncio
2
+ import asyncio.subprocess
3
+ import re
4
+ import aiohttp
5
+ import os
6
+ import platform
7
+ import sys
8
+ from dotenv import load_dotenv
9
+
10
+ CONFIG_DIR = os.path.expanduser("~/.guga")
11
+ env_path = os.path.join(CONFIG_DIR, '.env')
12
+ load_dotenv(dotenv_path=env_path)
13
+
14
+ # Enforce Linux-only restriction
15
+ if platform.system() != "Linux":
16
+ print("❌ ERROR: OS Notification monitoring only works on Linux (D-Bus required).")
17
+ print(f"Current OS: {platform.system()}")
18
+ sys.exit(1)
19
+
20
+ # ------------------------------------------------------------
21
+ # Configuration
22
+ # ------------------------------------------------------------
23
+ SERVER_URL = os.getenv("ALERTER_SERVER_URL", "http://localhost:6769/send")
24
+ LOG_FILE = os.path.join(CONFIG_DIR, "alerter.log")
25
+
26
+ # ------------------------------------------------------------
27
+ # Text Cleaning (Stripping Formatting)
28
+ # ------------------------------------------------------------
29
+ def clean_text(text: str) -> str:
30
+ """
31
+ Strips HTML-like tags and common markdown formatting from text.
32
+ """
33
+ if not text:
34
+ return ""
35
+
36
+ # 1. Strip HTML tags (e.g., <b>, <i>, <a href="...">)
37
+ text = re.sub(r'<[^>]+>', '', text)
38
+
39
+ # 2. Strip Markdown bold/italic/strike (e.g., **, *, __, _, ~~)
40
+ text = re.sub(r'(\*\*|__|\*|_|~~)', '', text)
41
+
42
+ # 3. Strip Markdown links [text](url) -> text
43
+ text = re.sub(r'\[([^\]]+)\]\([^\)]+\)', r'\1', text)
44
+
45
+ # 4. Strip excessive newlines and whitespace
46
+ text = re.sub(r'\n+', ' ', text)
47
+ text = text.strip()
48
+
49
+ return text
50
+
51
+ # ------------------------------------------------------------
52
+ # Forwarding Logic
53
+ # ------------------------------------------------------------
54
+ async def forward_to_server(app_name: str, title: str, body: str):
55
+ """
56
+ Sends the cleaned notification to the local server's /send route.
57
+ """
58
+ clean_title = clean_text(title)
59
+ clean_body = clean_text(body)
60
+
61
+ payload_msg = f"{clean_title}: {clean_body}"
62
+ if not clean_title and not clean_body:
63
+ return
64
+
65
+ log_entry = f"Forwarding: {payload_msg}\n"
66
+ print(log_entry.strip())
67
+ with open(LOG_FILE, "a") as f:
68
+ f.write(log_entry)
69
+
70
+ try:
71
+ async with aiohttp.ClientSession() as session:
72
+ async with session.post(SERVER_URL, json={"message": payload_msg , "title":app_name}) as resp:
73
+ status_msg = f"Server Response: {resp.status}\n"
74
+ print(status_msg.strip())
75
+ with open(LOG_FILE, "a") as f:
76
+ f.write(status_msg)
77
+ except Exception as e:
78
+ err_msg = f"Error forwarding: {e}\n"
79
+ print(err_msg.strip())
80
+ with open(LOG_FILE, "a") as f:
81
+ f.write(err_msg)
82
+
83
+ # ------------------------------------------------------------
84
+ # D-Bus Monitor via Subprocess
85
+ # ------------------------------------------------------------
86
+ async def monitor_notifications():
87
+ """
88
+ Runs dbus-monitor and parses its output to detect notifications.
89
+ """
90
+ # Explicitly filter for method_call to avoid duplicates from signals
91
+ cmd = ["dbus-monitor", "type='method_call',interface='org.freedesktop.Notifications',member='Notify'"]
92
+
93
+ try:
94
+ proc = await asyncio.create_subprocess_exec(
95
+ *cmd,
96
+ stdout=asyncio.subprocess.PIPE,
97
+ stderr=asyncio.subprocess.STDOUT
98
+ )
99
+ except Exception as e:
100
+ print(f"Failed to start dbus-monitor: {e}")
101
+ return
102
+
103
+ if not proc.stdout:
104
+ print("Failed to capture dbus-monitor stdout.")
105
+ return
106
+
107
+ print("Monitoring D-Bus for notifications (method calls only)...")
108
+
109
+ # State tracking
110
+ state = "IDLE"
111
+ app_name = ""
112
+ summary = ""
113
+ body = ""
114
+
115
+ while True:
116
+ line_bytes = await proc.stdout.readline()
117
+ if not line_bytes:
118
+ break
119
+
120
+ line = line_bytes.decode(errors='replace').strip()
121
+
122
+ # Detect start of method call specifically
123
+ if "method call" in line and "interface=org.freedesktop.Notifications; member=Notify" in line:
124
+ state = "APP_NAME"
125
+ app_name = ""
126
+ summary = ""
127
+ body = ""
128
+ continue
129
+
130
+ if state == "APP_NAME":
131
+ match = re.search(r'string\s+"(.*)"', line)
132
+ if match:
133
+ app_name = match.group(1)
134
+ state = "REPLACES_ID"
135
+
136
+ elif state == "REPLACES_ID":
137
+ if "uint32" in line:
138
+ state = "ICON"
139
+
140
+ elif state == "ICON":
141
+ match = re.search(r'string\s+"(.*)"', line)
142
+ if match:
143
+ state = "SUMMARY"
144
+
145
+ elif state == "SUMMARY":
146
+ match = re.search(r'string\s+"(.*)"', line)
147
+ if match:
148
+ summary = match.group(1)
149
+ state = "BODY"
150
+
151
+ elif state == "BODY":
152
+ # Body can be a string or we might see 'array [' if body is empty
153
+ match = re.search(r'string\s+"(.*)"', line)
154
+ if match:
155
+ body = match.group(1)
156
+ # Done capturing this notification
157
+ print(f"\n[Intercepted] App: {app_name}")
158
+ with open(LOG_FILE, "a") as f:
159
+ f.write(f"\n[Intercepted] App: {app_name}\nTitle: {summary}\nBody: {body}\n")
160
+ asyncio.create_task(forward_to_server(app_name, summary, body))
161
+ state = "IDLE"
162
+ elif "array [" in line:
163
+ # Body was empty, moving to actions
164
+ print(f"\n[Intercepted] App: {app_name} (No body)")
165
+ with open(LOG_FILE, "a") as f:
166
+ f.write(f"\n[Intercepted] App: {app_name}\nTitle: {summary}\nBody: (empty)\n")
167
+ asyncio.create_task(forward_to_server(app_name, summary, ""))
168
+ state = "IDLE"
169
+
170
+ if __name__ == "__main__":
171
+ try:
172
+ asyncio.run(monitor_notifications())
173
+ except KeyboardInterrupt:
174
+ print("\nStopping OS Notification Alerter...")