From 5254524ee04806b4a950b98b81afccc9c91e9e2e Mon Sep 17 00:00:00 2001 From: "N0\\A" Date: Fri, 24 Oct 2025 12:35:48 +0200 Subject: [PATCH] qol + discord crash bug fix --- SUPERCOPY.py | 4 +- core/discord_presence.py | 109 +++++++++++++++++++++++++-------------- main.py | 26 ++++++++-- 3 files changed, 94 insertions(+), 45 deletions(-) diff --git a/SUPERCOPY.py b/SUPERCOPY.py index d607aed..1ddc516 100644 --- a/SUPERCOPY.py +++ b/SUPERCOPY.py @@ -5,7 +5,9 @@ files = [ "core/headers.py", "core/updater.py", "core/web_search.py", - "main.py" + "main.py", + "README.md", + "requirements.txt" ] codeblock = "```" diff --git a/core/discord_presence.py b/core/discord_presence.py index 202ba50..0b201c7 100644 --- a/core/discord_presence.py +++ b/core/discord_presence.py @@ -1,4 +1,5 @@ import time +import threading from discordrp import Presence class DiscordPresence: @@ -7,61 +8,89 @@ class DiscordPresence: self.presence = None self.running = False self.start_time = None - + self._thread = None + self._stop_thread = threading.Event() + def start(self): - """Start the Discord Rich Presence""" if self.running: print("Presence is already running") return - self.start_time = int(time.time()) - self.presence = Presence(self.client_id) - self.presence.__enter__() - - self.presence.set( - { - "assets": { - "large_image": "2ktanbig", - "large_text": "CLARA" - }, - "buttons": [ - { - "label": "Let CLARA help you!", - "url": "https://github.com/n0va-bot/CLARA" - } - ] - } - ) - self.running = True - print("Discord presence started") - - def end(self): - """Stop the Discord Rich Presence""" - if not self.running: - print("Presence is not running") + self._stop_thread.clear() + self._thread = threading.Thread(target=self._run_loop, daemon=True) + self._thread.start() + print("Discord presence manager started") + + def _run_loop(self): + while not self._stop_thread.is_set(): + try: + with Presence(self.client_id) as presence: + self.presence = presence + print("Successfully connected to Discord RPC.") + self.start_time = int(time.time()) + self._set_initial_presence() + + while not self._stop_thread.is_set(): + time.sleep(15) + + except Exception as e: + self.presence = None + print(f"Failed to connect to Discord RPC: {e}. Retrying in 30 seconds...") + + for _ in range(30): + if self._stop_thread.is_set(): + break + time.sleep(1) + + self.presence = None + + def _set_initial_presence(self): + if not self.presence: return try: - if self.presence: - self.presence.__exit__(None, None, None) - self.presence = None + self.presence.set( + { + "assets": { + "large_image": "2ktanbig", + "large_text": "CLARA" + }, + "buttons": [ + { + "label": "Let CLARA help you!", + "url": "https://github.com/n0va-bot/CLARA" + } + ] + } + ) except Exception as e: - print(f"Error closing presence: {e}") - finally: - self.running = False - print("Discord presence stopped") - + print(f"Failed to set initial Discord presence: {e}") + + def end(self): + if not self.running: + print("Presence is not running") + return + + print("Stopping Discord presence...") + self._stop_thread.set() + if self._thread and self._thread.is_alive(): + self._thread.join(timeout=5) + + self.running = False + self.presence = None + print("Discord presence stopped") + def update(self, data): - """Update the presence with new data""" if not self.running or not self.presence: - print("Presence is not running. Call start() first.") return - self.presence.set(data) - + try: + self.presence.set(data) + except Exception as e: + print(f"Failed to update Discord presence: {e}") + def __del__(self): - """Cleanup when object is destroyed""" if self.running: self.end() diff --git a/main.py b/main.py index 07941cd..6234f30 100644 --- a/main.py +++ b/main.py @@ -362,6 +362,7 @@ class MainWindow(QtWidgets.QMainWindow): if not no_quit: right_menu.addAction("Quit", QtWidgets.QApplication.quit) self.tray.setContextMenu(right_menu) + self.tray.activated.connect(self.handle_tray_activated) self.tray.show() # LEFT MENU @@ -410,15 +411,26 @@ class MainWindow(QtWidgets.QMainWindow): elif event.button() == QtCore.Qt.RightButton: #type: ignore self.tray.contextMenu().popup(event.globalPosition().toPoint()) + def handle_tray_activated(self, reason): + if reason == QtWidgets.QSystemTrayIcon.ActivationReason.Trigger: + self.left_menu.popup(QtGui.QCursor.pos()) + def toggle_visible(self): self.setVisible(not self.isVisible()) def start_app_launcher(self): self.app_launcher_dialog = AppLauncherDialog(self) + self.app_launcher_dialog.move(QtGui.QCursor.pos()) self.app_launcher_dialog.show() def start_file_search(self): - pattern, ok = QtWidgets.QInputDialog.getText(self, "File Search", "Enter search pattern:") + dialog = QtWidgets.QInputDialog(self) + dialog.setWindowTitle("File Search") + dialog.setLabelText("Enter search pattern:") + dialog.move(QtGui.QCursor.pos()) + + ok = dialog.exec() + pattern = dialog.textValue() if ok and pattern: try: @@ -453,7 +465,14 @@ class MainWindow(QtWidgets.QMainWindow): QtWidgets.QMessageBox.information(self, "No Results", "Sorry, I couldn't find anything in the root folder either.") def start_web_search(self): - query, ok = QtWidgets.QInputDialog.getText(self, "Web Search", "Enter search query:") + dialog = QtWidgets.QInputDialog(self) + dialog.setWindowTitle("Web Search") + dialog.setLabelText("Enter search query:") + dialog.move(QtGui.QCursor.pos()) + + ok = dialog.exec() + query = dialog.textValue() + if ok and query: try: QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) #type: ignore @@ -527,10 +546,9 @@ def main(): pet.show() - # Gracefully handle shutdown app.aboutToQuit.connect(presence.end) sys.exit(app.exec()) if __name__ == "__main__": - main() + main() \ No newline at end of file