Files
Mark-XXXIX-OR/reminder.py
T
2026-05-10 17:04:19 +03:00

208 lines
8.8 KiB
Python

# actions/open_app.py
# MARK XXV — Cross-Platform App Launcher
import time
import subprocess
import platform
import shutil
try:
import psutil
_PSUTIL = True
except ImportError:
_PSUTIL = False
_APP_ALIASES = {
"whatsapp": {"Windows": "WhatsApp", "Darwin": "WhatsApp", "Linux": "whatsapp"},
"chrome": {"Windows": "chrome", "Darwin": "Google Chrome", "Linux": "google-chrome"},
"google chrome": {"Windows": "chrome", "Darwin": "Google Chrome", "Linux": "google-chrome"},
"firefox": {"Windows": "firefox", "Darwin": "Firefox", "Linux": "firefox"},
"spotify": {"Windows": "Spotify", "Darwin": "Spotify", "Linux": "spotify"},
"vscode": {"Windows": "code", "Darwin": "Visual Studio Code", "Linux": "code"},
"visual studio code": {"Windows": "code", "Darwin": "Visual Studio Code", "Linux": "code"},
"discord": {"Windows": "Discord", "Darwin": "Discord", "Linux": "discord"},
"telegram": {"Windows": "Telegram", "Darwin": "Telegram", "Linux": "telegram"},
"instagram": {"Windows": "Instagram", "Darwin": "Instagram", "Linux": "instagram"},
"tiktok": {"Windows": "TikTok", "Darwin": "TikTok", "Linux": "tiktok"},
"notepad": {"Windows": "notepad.exe", "Darwin": "TextEdit", "Linux": "gedit"},
"calculator": {"Windows": "calc.exe", "Darwin": "Calculator", "Linux": "gnome-calculator"},
"terminal": {"Windows": "cmd.exe", "Darwin": "Terminal", "Linux": "gnome-terminal"},
"cmd": {"Windows": "cmd.exe", "Darwin": "Terminal", "Linux": "bash"},
"explorer": {"Windows": "explorer.exe", "Darwin": "Finder", "Linux": "nautilus"},
"file explorer": {"Windows": "explorer.exe", "Darwin": "Finder", "Linux": "nautilus"},
"paint": {"Windows": "mspaint.exe", "Darwin": "Preview", "Linux": "gimp"},
"word": {"Windows": "winword", "Darwin": "Microsoft Word", "Linux": "libreoffice --writer"},
"excel": {"Windows": "excel", "Darwin": "Microsoft Excel", "Linux": "libreoffice --calc"},
"powerpoint": {"Windows": "powerpnt", "Darwin": "Microsoft PowerPoint","Linux": "libreoffice --impress"},
"vlc": {"Windows": "vlc", "Darwin": "VLC", "Linux": "vlc"},
"zoom": {"Windows": "Zoom", "Darwin": "zoom.us", "Linux": "zoom"},
"slack": {"Windows": "Slack", "Darwin": "Slack", "Linux": "slack"},
"steam": {"Windows": "steam", "Darwin": "Steam", "Linux": "steam"},
"task manager": {"Windows": "taskmgr.exe", "Darwin": "Activity Monitor", "Linux": "gnome-system-monitor"},
"settings": {"Windows": "ms-settings:", "Darwin": "System Preferences", "Linux": "gnome-control-center"},
"powershell": {"Windows": "powershell.exe", "Darwin": "Terminal", "Linux": "bash"},
"edge": {"Windows": "msedge", "Darwin": "Microsoft Edge", "Linux": "microsoft-edge"},
"brave": {"Windows": "brave", "Darwin": "Brave Browser", "Linux": "brave-browser"},
"obsidian": {"Windows": "Obsidian", "Darwin": "Obsidian", "Linux": "obsidian"},
"notion": {"Windows": "Notion", "Darwin": "Notion", "Linux": "notion"},
"blender": {"Windows": "blender", "Darwin": "Blender", "Linux": "blender"},
"capcut": {"Windows": "CapCut", "Darwin": "CapCut", "Linux": "capcut"},
"postman": {"Windows": "Postman", "Darwin": "Postman", "Linux": "postman"},
"figma": {"Windows": "Figma", "Darwin": "Figma", "Linux": "figma"},
}
def _normalize(raw: str) -> str:
system = platform.system()
key = raw.lower().strip()
if key in _APP_ALIASES:
return _APP_ALIASES[key].get(system, raw)
for alias_key, os_map in _APP_ALIASES.items():
if alias_key in key or key in alias_key:
return os_map.get(system, raw)
return raw
def _is_running(app_name: str) -> bool:
if not _PSUTIL:
return True
app_lower = app_name.lower().replace(" ", "").replace(".exe", "")
try:
for proc in psutil.process_iter(["name"]):
try:
proc_name = proc.info["name"].lower().replace(" ", "").replace(".exe", "")
if app_lower in proc_name or proc_name in app_lower:
return True
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
except Exception:
pass
return False
def _launch_windows(app_name: str) -> bool:
try:
import pyautogui
pyautogui.PAUSE = 0.1
pyautogui.press("win")
time.sleep(0.6)
pyautogui.write(app_name, interval=0.05)
time.sleep(0.8)
pyautogui.press("enter")
time.sleep(3.0)
return True
except Exception as e:
print(f"[open_app] ⚠️ Windows launch failed: {e}")
return False
def _launch_macos(app_name: str) -> bool:
try:
result = subprocess.run(["open", "-a", app_name], capture_output=True, timeout=8)
if result.returncode == 0:
time.sleep(1.0)
return True
except Exception:
pass
try:
result = subprocess.run(["open", "-a", f"{app_name}.app"], capture_output=True, timeout=8)
if result.returncode == 0:
time.sleep(1.0)
return True
except Exception:
pass
try:
import pyautogui
pyautogui.hotkey("command", "space")
time.sleep(0.6)
pyautogui.write(app_name, interval=0.05)
time.sleep(0.8)
pyautogui.press("enter")
time.sleep(1.5)
return True
except Exception as e:
print(f"[open_app] ⚠️ macOS Spotlight failed: {e}")
return False
def _launch_linux(app_name: str) -> bool:
binary = (
shutil.which(app_name) or
shutil.which(app_name.lower()) or
shutil.which(app_name.lower().replace(" ", "-"))
)
if binary:
try:
subprocess.Popen([binary], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
time.sleep(1.0)
return True
except Exception:
pass
try:
subprocess.run(["xdg-open", app_name], capture_output=True, timeout=5)
return True
except Exception:
pass
try:
desktop_name = app_name.lower().replace(" ", "-")
subprocess.run(["gtk-launch", desktop_name], capture_output=True, timeout=5)
return True
except Exception:
pass
return False
_OS_LAUNCHERS = {
"Windows": _launch_windows,
"Darwin": _launch_macos,
"Linux": _launch_linux,
}
def open_app(
parameters=None,
response=None,
player=None,
session_memory=None,
) -> str:
app_name = (parameters or {}).get("app_name", "").strip()
if not app_name:
return "Please specify which application to open, sir."
system = platform.system()
launcher = _OS_LAUNCHERS.get(system)
if launcher is None:
return f"Unsupported OS: {system}"
normalized = _normalize(app_name)
print(f"[open_app] 🚀 Launching: {app_name} → {normalized} ({system})")
if player:
player.write_log(f"[open_app] {app_name}")
try:
success = launcher(normalized)
if success:
return f"Opened {app_name} successfully, sir."
if normalized != app_name:
success = launcher(app_name)
if success:
return f"Opened {app_name} successfully, sir."
return (
f"I tried to open {app_name}, sir, but couldn't confirm it launched. "
f"It may still be loading or might not be installed."
)
except Exception as e:
print(f"[open_app] ❌ {e}")
return f"Failed to open {app_name}, sir: {e}"