Files
luk/src/utils/notifications.py
2025-08-06 15:35:40 -05:00

91 lines
2.4 KiB
Python

"""
macOS notification utilities for GTD terminal tools.
"""
import subprocess
import platform
from typing import Optional
def send_notification(
title: str,
message: str,
subtitle: Optional[str] = None,
sound: Optional[str] = None,
) -> bool:
"""
Send a macOS notification using osascript.
Args:
title: The notification title
message: The notification message body
subtitle: Optional subtitle
sound: Optional sound name (e.g., "default", "Glass", "Ping")
Returns:
bool: True if notification was sent successfully, False otherwise
"""
if platform.system() != "Darwin":
return False
try:
# Escape quotes for AppleScript string literals
def escape_applescript_string(text: str) -> str:
return text.replace("\\", "\\\\").replace('"', '\\"')
escaped_title = escape_applescript_string(title)
escaped_message = escape_applescript_string(message)
# Build the AppleScript command
script_parts = [
f'display notification "{escaped_message}"',
f'with title "{escaped_title}"',
]
if subtitle:
escaped_subtitle = escape_applescript_string(subtitle)
script_parts.append(f'subtitle "{escaped_subtitle}"')
if sound:
escaped_sound = escape_applescript_string(sound)
script_parts.append(f'sound name "{escaped_sound}"')
script = " ".join(script_parts)
# Execute the notification by passing script through stdin
subprocess.run(
["osascript"], input=script, check=True, capture_output=True, text=True
)
return True
except subprocess.CalledProcessError:
return False
except Exception:
return False
except Exception:
return False
except Exception:
return False
def notify_new_emails(count: int, org: str = ""):
"""
Send notification about new email messages.
Args:
count: Number of new messages
org: Organization name (optional)
"""
if count <= 0:
return
if count == 1:
title = "New Email"
message = "You have 1 new message"
else:
title = "New Emails"
message = f"You have {count} new messages"
subtitle = f"from {org}" if org else None
send_notification(title=title, message=message, subtitle=subtitle, sound="default")