import os import subprocess import sys import threading import time import webbrowser from datetime import date, datetime import pyautogui import speech_recognition as sr from PySide6.QtCore import QObject, Signal from PySide6.QtGui import QIcon from PySide6.QtWidgets import QApplication, QMenu, QSystemTrayIcon from audio.tts import speak from bs.verity import ouiouioui # External file imports from core.ui import RisaAssistantPopup from utils.ai_client import ask_ai from utils.time_utils import time_to_words from utils.weather import get_local_weather popup_window = None trigger_bridge = None tray_icon = None recognizer = sr.Recognizer() microphone = sr.Microphone() recognizer.dynamic_energy_threshold = True recognizer.pause_threshold = 0.8 class VoiceTriggerBridge(QObject): hide_window = Signal() show_input_panel = Signal() show_thinking_panel = Signal(str) update_display_card = Signal(str, dict) show_timeout_card = Signal(str) update_state = Signal(str) # Commands def process_command(command: str) -> bool: global trigger_bridge command = command.lower().strip() if not command: return False print(f"Executing command: '{command}'") # Time Commands if any(word in command for word in ["time", "what time", "current time"]): now = datetime.now() time_words = time_to_words(now) if trigger_bridge: time_data = { "time": now.strftime("%I:%M %p").lstrip('0'), "day": now.strftime("%A"), "date": now.strftime("%B %d, %Y") } trigger_bridge.update_display_card.emit("time", time_data) speak(f"The time is {time_words}") return True elif any(word in command for word in ["date", "what's the date"]): today_date = date.today().strftime("%B %d, %Y") if trigger_bridge: trigger_bridge.update_display_card.emit("general", {"text": f"Today is {today_date}."}) speak(f"The date is {today_date}") return True # Weather elif any(word in command for word in ["weather", "weather today", "what is the weather"]): weather = get_local_weather() if weather: city = weather['location']['city'] temp_unit = weather['units']['temp'] current_temp = weather['current_temp'] high_temp = weather['high_temp'] low_temp = weather['low_temp'] clouds = weather['cloud_cover_pct'] rain = weather['precipitation'] if clouds < 10: cloud_phrase = "Clear skies" elif clouds < 40: cloud_phrase = "Partly cloudy skies" elif clouds < 75: cloud_phrase = "Mostly cloudy skies" else: cloud_phrase = "Completely overcast" if rain > 0: cloud_phrase += ", rain soon." if trigger_bridge: trigger_bridge.update_display_card.emit("weather", { "temp": str(current_temp), "humidity": str(clouds), "high": str(high_temp), "low": str(low_temp), "condition": cloud_phrase, "location": f"{city} NJ" }) print(f"Right now in {city}, it is {current_temp}{temp_unit} with {cloud_phrase.lower()}. Today's high will be {high_temp} degrees, and the low will be {low_temp} degrees.") speak(f"Right now in {city}, it is {current_temp}{temp_unit} with {cloud_phrase.lower()}. Today's high will be {high_temp} degrees, and the low will be {low_temp} degrees.") return True return False # Identity elif any(phrase in command for phrase in ["who are you", "your name", "what do you do"]): if trigger_bridge: trigger_bridge.update_display_card.emit("general", {"text": "Hi, my name is Risa. I'm your voice assistant."}) speak("Hi, my name is Risa. I'm your voice assistant.") return True elif any(phrase in command for phrase in ["what is the capital of france", "What is the capital of france", "What's the capital of france"]): if trigger_bridge: trigger_bridge.update_display_card.emit("general", {"text": "Oui oui oui! It paris"}) ouiouioui() return True # Media Controls elif any(phrase in command for phrase in ["pause", "pause music", "pause video", "play", "resume"]): pyautogui.press('playpause') speak("Done") return True elif "volume up" in command: for _ in range(5): pyautogui.press("volumeup") speak("Volume up") return True elif "volume down" in command: for _ in range(5): pyautogui.press("volumedown") speak("Volume down") return True elif "mute" in command: pyautogui.press("volumemute") return True # Web Controls elif "open google" in command: speak("Opening Google") webbrowser.open("https://google.com") return True elif "open youtube" in command: speak("Opening Youtube") webbrowser.open("https://youtube.com") return True elif "search for" in command: query = command.split("search for")[-1].strip() if query: if trigger_bridge: trigger_bridge.update_display_card.emit("general", {"text": f"Searching Google for: {query}"}) speak(f"Searching for {query}") webbrowser.open(f"https://www.google.com/search?q={query}") return True # Apps elif "open calculator" in command: speak("Opening Calculator") if os.name == 'nt': subprocess.Popen('calc.exe') else: subprocess.Popen('gnome-calculator' if os.name == 'posix' else 'open -a Calculator') return True # Sleep elif any(phrase in command for phrase in ["stop listening", "go to sleep", "hide"]): speak("Going to sleep.") if popup_window and trigger_bridge: trigger_bridge.hide_window.emit() trigger_bridge.update_state.emit("idle") return False # Commands List elif any(phrase in command for phrase in ["list commands", "what are your commands", "show commands"]): commands_html = """
| • Time / Date: "What time is it?", "What's the date?" |
| • Weather: "What is the weather today?" |
| • Controls: "Volume up/down", "Mute", "Pause/Play" |
| • Apps & Web: "Open Google", "Search for [query]" |
| • AI Core: "Ask AI [your question]" |
| • Sleep: "Stop listening", "Go to sleep" |