Загрузка данных


import json
import os
import shutil
import webbrowser
import datetime
import speech_recognition as sr
from gtts import gTTS
import pygame
from groq import Groq
import pyautogui
import psutil
import time

client = Groq(api_key="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")

MEMORY_FILE = "nova_memory.json"
SETTINGS_FILE = "nova_settings.json"

def load_settings():
    if os.path.exists(SETTINGS_FILE):
        try:
            with open(SETTINGS_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        except Exception:
            return {"user_name": "друг", "lang": "ru"}
    return {"user_name": "друг", "lang": "ru"}

def save_settings(settings):
    try:
        with open(SETTINGS_FILE, "w", encoding="utf-8") as f:
            json.dump(settings, f, ensure_ascii=False, indent=2)
    except Exception as e:
        print(f"Ошибка сохранения настроек: {e}")

def load_memory():
    if os.path.exists(MEMORY_FILE):
        try:
            with open(MEMORY_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        except Exception:
            return []
    return []

def save_memory():
    try:
        with open(MEMORY_FILE, "w", encoding="utf-8") as f:
            json.dump(chat_history, f, ensure_ascii=False, indent=2)
    except Exception as e:
        print(f"Ошибка сохранения памяти: {e}")

chat_history = load_memory()
app_settings = load_settings()
user_name = app_settings.get("user_name", "друг")
current_lang = app_settings.get("lang", "ru")

def speak(text, lang=None):
    use_lang = lang if lang else current_lang
    print(f"Нова [{use_lang}]: {text}")
    try:
        tts = gTTS(text=text, lang=use_lang)
        audio_file = "temp_voice.mp3"
        tts.save(audio_file)
        
        pygame.mixer.init()
        pygame.mixer.music.load(audio_file)
        pygame.mixer.music.play()
        while pygame.mixer.music.get_busy():
            pygame.time.Clock().tick(10)
        pygame.mixer.quit()
        
        if os.path.exists(audio_file):
            os.remove(audio_file)
    except Exception as e:
        print(f"Ошибка озвучки: {e}")

def listen():
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("\nСлушаю...")
        r.adjust_for_ambient_noise(source, duration=0.5)
        try:
            audio = r.listen(source, timeout=5, phrase_time_limit=10)
        except sr.WaitTimeoutError:
            return ""
            
    try:
        rec_lang = "ru-RU" if current_lang == "ru" else "en-US"
        command = r.recognize_google(audio, language=rec_lang)
        print(f"Вы сказали: {command}")
        return command
    except sr.UnknownValueError:
        return ""
    except sr.RequestError:
        print("Ошибка соединения с сервисом распознавания речи.")
        return ""

def parse_intent_with_ai(user_speech):
    global chat_history, user_name, current_lang
    chat_history.append(f"{user_name}: {user_speech}")
    
    context_slice = chat_history[-10:]
    context_str = "\n".join(context_slice)

    prompt = f"""
    Ты — Нова, элитный голосовой ассистент на ПК. Пользователя зовут "{user_name}". Текущий язык: "{current_lang}".
    Проанализируй фразу и верни СТРОГО JSON без markdown-оформления (без ```json):
    {{
      "action": "open_chat", "change_language", "set_name", "open_youtube", "google_search", "open_app", 
      "open_folder", "empty_recycle_bin", "shutdown_pc", "cancel_shutdown", "sleep_pc", 
      "time_info", "battery_info", "take_screenshot", "create_note", "copy_files", "exit", или "chat",
      "messenger": "telegram, discord или whatsapp",
      "chat_target": "имя контакта или чата",
      "new_lang": "код языка",
      "new_name": "новое имя",
      "query": "поисковый запрос",
      "app_name": "программа",
      "folder_name": "папка",
      "minutes": 0,
      "note_text": "текст",
      "source_path": "",
      "dest_path": "",
      "text": "ответ пользователю"
    }}

    История разговора:
    {context_str}
    
    Текущая фраза: "{user_speech}"
    """
    
    try:
        completion = client.chat.completions.create(
            model="llama-3.3-70b-versatile",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.1
        )
        clean_text = completion.choices[0].message.content.replace("```json", "").replace("```", "").strip()
        result = json.loads(clean_text)
        
        if result.get("action") == "change_language":
            n_lang = result.get("new_lang")
            if n_lang:
                current_lang = n_lang.lower()
                app_settings["lang"] = current_lang
                save_settings(app_settings)
                
        if result.get("action") == "set_name":
            new_n = result.get("new_name")
            if new_n:
                user_name = new_n
                app_settings["user_name"] = user_name
                save_settings(app_settings)
                
        if result.get("action") in ["chat", "set_name", "change_language", "open_chat"]:
            chat_history.append(f"Нова: {result.get('text')}")
            
        save_memory()
        return result
    except Exception as e:
        print(f"Ошибка ИИ Groq: {e}")
        return {"action": "chat", "text": "Я не совсем поняла команду, повторите пожалуйста."}

def execute_action(intent):
    action = intent.get("action")
    
    if action == "open_chat":
        messenger = intent.get("messenger", "").lower()
        target = intent.get("chat_target", "")
        speak(f"Открываю чат с пользователем {target} в приложении {messenger}.")
        
        if "telegram" in messenger:
            os.system("start telegram")
            time.sleep(2)
            pyautogui.hotkey('ctrl', 'k')
            time.sleep(0.5)
            pyautogui.write(target, interval=0.1)
            time.sleep(1)
            pyautogui.press('enter')
        elif "discord" in messenger or "дискорд" in messenger:
            os.system("start discord")
            time.sleep(2)
            pyautogui.hotkey('ctrl', 'k')
            time.sleep(0.5)
            pyautogui.write(target, interval=0.1)
            time.sleep(1)
            pyautogui.press('enter')
        else:
            speak("Не удалось определить мессенджер для открытия чата.")

    elif action == "change_language":
        speak(intent.get("text", "Я сменила язык."))
        
    elif action == "open_youtube":
        q = intent.get("query", "")
        webbrowser.open(f"[https://www.youtube.com/results?search_query=](https://www.youtube.com/results?search_query=){q}")
        speak(f"Ищу на ютубе: {q}")
        
    elif action == "google_search":
        q = intent.get("query", "")
        webbrowser.open(f"[https://www.google.com/search?q=](https://www.google.com/search?q=){q}")
        speak("Ищу в интернете.")
        
    elif action == "open_app":
        app = intent.get("app_name", "").lower()
        if "steam" in app: os.system("start steam://")
        elif "calc" in app or "калькулятор" in app: os.system("calc")
        elif "discord" in app: os.system("start discord")
        elif "telegram" in app: os.system("start telegram")
        elif "chrome" in app or "браузер" in app: os.system("start chrome")
        elif "notepad" in app or "блокнот" in app: os.system("notepad")
        elif "code" in app or "vs code" in app: os.system("code")
        speak("Запускаю приложение.")
        
    elif action == "open_folder":
        folder = intent.get("folder_name", "").lower()
        userprofile = os.environ.get("USERPROFILE", "C:\\Users\\Default")
        path_to_open = ""
        if "загруз" in folder or "downloads" in folder:
            path_to_open = os.path.join(userprofile, "Downloads")
        elif "документ" in folder or "documents" in folder:
            path_to_open = os.path.join(userprofile, "Documents")
        elif "рабочий стол" in folder or "desktop" in folder:
            path_to_open = os.path.join(userprofile, "Desktop")
        else:
            path_to_open = folder
            
        if path_to_open and os.path.exists(path_to_open):
            os.startfile(path_to_open)
            speak("Открываю папку.")
        else:
            speak("Не удалось найти указанную папку.")
            
    elif action == "empty_recycle_bin":
        try:
            os.system("PowerShell -Command \"Clear-RecycleBin -Force -ErrorAction SilentlyContinue\"")
            speak("Корзина успешно очищена.")
        except Exception as e:
            speak(f"Не удалось очистить корзину: {e}")
            
    elif action == "shutdown_pc":
        minutes = int(intent.get("minutes", 0))
        if minutes > 0:
            os.system(f"shutdown /s /t {minutes * 60}")
            speak(f"Компьютер выключится через {minutes} минут.")
        else:
            os.system("shutdown /s /t 60")
            speak("Компьютер выключится через минуту.")
            
    elif action == "cancel_shutdown":
        os.system("shutdown /a")
        speak("Отменила выключение компьютера.")
        
    elif action == "sleep_pc":
        speak("Перевожу компьютер в спящий режим.")
        os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
        
    elif action == "time_info":
        now = datetime.datetime.now().strftime("%H:%M")
        speak(f"Текущее время: {now}")
        
    elif action == "battery_info":
        battery = psutil.sensors_battery()
        if battery:
            plugged = "подключен к зарядке" if battery.power_plugged else "работает от батареи"
            speak(f"Заряд батареи {battery.percent} процентов, компьютер {plugged}.")
        else:
            speak("Не удалось определить состояние батареи.")
            
    elif action == "take_screenshot":
        try:
            os.makedirs("screenshots", exist_ok=True)
            filename = f"screenshots/shot_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
            pyautogui.screenshot().save(filename)
            speak("Скриншот успешно сохранен.")
        except Exception as e:
            speak(f"Не удалось сделать скриншот: {e}")
            
    elif action == "create_note":
        text = intent.get("note_text", "Пустая заметка")
        with open("nova_notes.txt", "a", encoding="utf-8") as f:
            f.write(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}] {text}\n")
        speak("Записала в блокнот.")
        
    elif action == "copy_files":
        src = intent.get("source_path")
        dst = intent.get("dest_path")
        try:
            if src and dst and os.path.exists(src):
                if os.path.isdir(src):
                    shutil.copytree(src, dst, dirs_exist_ok=True)
                else:
                    shutil.copy(src, dst)
                speak("Файлы успешно скопированы.")
            else:
                speak("Не найден указанный путь.")
        except Exception as e:
            speak(f"Ошибка копирования: {e}")
            
    elif action == "set_name":
        speak(intent.get("text", "Готово."))
        
    elif action == "exit":
        speak(f"До свидания, {user_name}!")
        exit()
        
    elif action == "chat":
        speak(intent.get("text", "Слушаю вас."))

if __name__ == "__main__":
    speak(f"Нова активирована. Рада вас слышать, {user_name}!")
    while True:
        cmd = listen()
        if cmd:
            intent_data = parse_intent_with_ai(cmd)
            execute_action(intent_data)