Spaces:
Running
Running
| """ | |
| modules/app_monitor.py β FRIDAY Tracks What's Playing | |
| Monitors active applications and detects: | |
| - What app is in focus | |
| - If video/audio is playing | |
| - Browser video detection | |
| - Media state detection | |
| """ | |
| import time | |
| import os | |
| import json | |
| import subprocess | |
| from config import DATA_DIR | |
| MONITOR_FILE = os.path.join(DATA_DIR, "app_monitor.json") | |
| def _load() -> dict: | |
| if not os.path.exists(MONITOR_FILE): | |
| return {"active": "", "title": "", "last_change": 0, "media_playing": False} | |
| try: | |
| with open(MONITOR_FILE, "r") as f: | |
| return json.load(f) | |
| except Exception: | |
| return {"active": "", "title": "", "last_change": 0, "media_playing": False} | |
| def _save(data: dict): | |
| os.makedirs(DATA_DIR, exist_ok=True) | |
| try: | |
| with open(MONITOR_FILE, "w") as f: | |
| json.dump(data, f, indent=2) | |
| except Exception: | |
| pass | |
| # ββ Get Active Window βββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_active_window() -> dict: | |
| """Get currently active window info.""" | |
| try: | |
| import psutil | |
| # Get foreground window | |
| foreground = psutil.Process()._proc.info.get('name') | |
| # Use Windows API for window title | |
| import ctypes | |
| from ctypes import wintypes | |
| user32 = ctypes.windll.user32 | |
| hwnd = user32.GetForegroundWindow() | |
| length = user32.GetWindowTextLengthW(hwnd) | |
| if length > 0: | |
| buffer = ctypes.create_unicode_buffer(length + 1) | |
| user32.GetWindowTextW(hwnd, buffer, length + 1) | |
| title = buffer.value | |
| else: | |
| title = "" | |
| return {"hwnd": hwnd, "title": title[:100], "time": time.time()} | |
| except Exception: | |
| return {"title": "", "time": time.time()} | |
| # ββ Detect Video Playing βββββββββββββββββββββββββββββββββββββ | |
| def is_video_playing() -> bool: | |
| """Detect if video/media is playing.""" | |
| data = _load() | |
| title = data.get("title", "").lower() | |
| active = data.get("active", "").lower() | |
| # Browser video detection | |
| video_patterns = ["youtube", "netflix", "prime", "disney", "hulu", "spotify", "twitch"] | |
| for pattern in video_patterns: | |
| if pattern in title or pattern in active: | |
| return True | |
| return is_media_playing() | |
| def get_current_app() -> str: | |
| """Get current active application.""" | |
| return _load().get("active", "") | |
| def get_current_title() -> str: | |
| """Get current window title.""" | |
| return _load().get("title", "") | |
| def get_current_app() -> str: | |
| """Get current active application.""" | |
| return _load().get("active", "") | |
| def get_current_title() -> str: | |
| """Get current window title.""" | |
| return _load().get("title", "") | |
| # ββ Background Monitor βββββββββββββββββββββββββββββββββββββββββ | |
| def check_active(): | |
| """Check and update active window.""" | |
| try: | |
| window = get_active_window() | |
| title = window.get("title", "") | |
| # Determine app from title | |
| app = "unknown" | |
| if "youtube" in title.lower(): | |
| app = "YouTube" | |
| elif "chrome" in title.lower(): | |
| app = "Chrome" | |
| elif "edge" in title.lower(): | |
| app = "Edge" | |
| elif "spotify" in title.lower(): | |
| app = "Spotify" | |
| elif "discord" in title.lower(): | |
| app = "Discord" | |
| elif "code" in title.lower(): | |
| app = "VS Code" | |
| elif "game" in title.lower(): | |
| app = "Game" | |
| data = _load() | |
| data["active"] = app | |
| data["title"] = title[:100] | |
| data["last_change"] = time.time() | |
| data["media_playing"] = title.lower().find("playing") > 0 or title.lower().find("youtube") > 0 | |
| _save(data) | |
| return data | |
| except Exception: | |
| return _load() | |
| # ββ Media State βββββββββββββββββββββββββββββββββββββββββββββββ | |
| def set_media_state(playing: bool): | |
| """Set media playing state.""" | |
| data = _load() | |
| data["media_playing"] = playing | |
| data["media_time"] = time.time() | |
| _save(data) | |
| def is_media_playing() -> bool: | |
| """Check if media is playing.""" | |
| return _load().get("media_playing", False) | |
| # ββ Background Loop ββββββββββββββββββββββββββββββββββββββββββ | |
| def start_monitor(): | |
| """Start app monitor in background.""" | |
| import threading | |
| import time | |
| def _loop(): | |
| while True: | |
| try: | |
| check_active() | |
| except Exception: | |
| pass | |
| time.sleep(2) # Check every 2 seconds | |
| t = threading.Thread(target=_loop, daemon=True) | |
| t.start() | |
| # ββ Brain Integration βββββββββββββββββββββββββββββββββββββββββ | |
| def get_app_context() -> str: | |
| """Get app context for brain.""" | |
| data = _load() | |
| parts = [] | |
| active = data.get("active", "") | |
| title = data.get("title", "") | |
| if active: | |
| parts.append(f"On: {active}") | |
| if is_media_playing(): | |
| parts.append("Media playing") | |
| if parts: | |
| return "[APP] " + " | ".join(parts) | |
| return "" |