@@ -40,7 +40,6 @@ class DuktoProtocol:
|
|||||||
# Callbacks
|
# Callbacks
|
||||||
self.on_peer_added: Optional[Callable[[Peer], None]] = None
|
self.on_peer_added: Optional[Callable[[Peer], None]] = None
|
||||||
self.on_peer_removed: Optional[Callable[[Peer], None]] = None
|
self.on_peer_removed: Optional[Callable[[Peer], None]] = None
|
||||||
self.on_receive_request: Optional[Callable[[str, int, int], bool]] = None
|
|
||||||
self.on_receive_start: Optional[Callable[[str], None]] = None
|
self.on_receive_start: Optional[Callable[[str], None]] = None
|
||||||
self.on_receive_complete: Optional[Callable[[List[str], int], None]] = None
|
self.on_receive_complete: Optional[Callable[[List[str], int], None]] = None
|
||||||
self.on_receive_text: Optional[Callable[[str, int], None]] = None
|
self.on_receive_text: Optional[Callable[[str, int], None]] = None
|
||||||
@@ -193,45 +192,29 @@ class DuktoProtocol:
|
|||||||
conn.close()
|
conn.close()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
threading.Thread(target=self._handle_connection_request,
|
threading.Thread(target=self._receive_files,
|
||||||
args=(conn, addr[0]), daemon=True).start()
|
args=(conn, addr[0]), daemon=True).start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if self.running:
|
if self.running:
|
||||||
print(f"TCP listener error: {e}")
|
print(f"TCP listener error: {e}")
|
||||||
|
|
||||||
def _handle_connection_request(self, conn: socket.socket, sender_ip: str):
|
def _receive_files(self, conn: socket.socket, sender_ip: str):
|
||||||
try:
|
|
||||||
conn.settimeout(10)
|
|
||||||
|
|
||||||
header = conn.recv(16)
|
|
||||||
if len(header) < 16:
|
|
||||||
conn.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
elements_count = struct.unpack('<Q', header[0:8])[0]
|
|
||||||
total_size = struct.unpack('<Q', header[8:16])[0]
|
|
||||||
|
|
||||||
accept_transfer = True
|
|
||||||
if self.on_receive_request:
|
|
||||||
accept_transfer = self.on_receive_request(sender_ip, elements_count, total_size)
|
|
||||||
|
|
||||||
if accept_transfer:
|
|
||||||
self._receive_files(conn, sender_ip, elements_count, total_size)
|
|
||||||
else:
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
if self.on_error:
|
|
||||||
self.on_error(f"Connection request error: {e}")
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
def _receive_files(self, conn: socket.socket, sender_ip: str, elements_count: int, total_size: int):
|
|
||||||
self.is_receiving = True
|
self.is_receiving = True
|
||||||
|
|
||||||
if self.on_receive_start:
|
if self.on_receive_start:
|
||||||
self.on_receive_start(sender_ip)
|
self.on_receive_start(sender_ip)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
conn.settimeout(10)
|
||||||
|
|
||||||
|
# Read header
|
||||||
|
header = conn.recv(16)
|
||||||
|
if len(header) < 16:
|
||||||
|
return
|
||||||
|
|
||||||
|
elements_count = struct.unpack('<Q', header[0:8])[0]
|
||||||
|
total_size = struct.unpack('<Q', header[8:16])[0]
|
||||||
|
|
||||||
conn.settimeout(None)
|
conn.settimeout(None)
|
||||||
|
|
||||||
received_files = []
|
received_files = []
|
||||||
|
|||||||
71
main.py
71
main.py
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import sys, os, subprocess, threading
|
import sys, os, subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PySide6 import QtCore, QtGui, QtWidgets
|
from PySide6 import QtCore, QtGui, QtWidgets
|
||||||
from pynput import keyboard
|
from pynput import keyboard
|
||||||
@@ -9,7 +9,6 @@ from core.web_search import MullvadLetaWrapper
|
|||||||
from core.discord_presence import presence
|
from core.discord_presence import presence
|
||||||
from core.app_launcher import list_apps, launch
|
from core.app_launcher import list_apps, launch
|
||||||
from core.updater import update_repository, is_update_available
|
from core.updater import update_repository, is_update_available
|
||||||
from core.dukto import DuktoProtocol
|
|
||||||
|
|
||||||
ASSET = Path(__file__).parent / "assets" / "2ktan.png"
|
ASSET = Path(__file__).parent / "assets" / "2ktan.png"
|
||||||
|
|
||||||
@@ -317,39 +316,10 @@ class WebSearchResults(QtWidgets.QDialog):
|
|||||||
QtWidgets.QApplication.restoreOverrideCursor()
|
QtWidgets.QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
|
||||||
class ReceiveConfirmationDialog(QtWidgets.QDialog):
|
|
||||||
def __init__(self, sender_ip, file_count, total_size, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setWindowTitle("Incoming Transfer")
|
|
||||||
|
|
||||||
size_mb = total_size / (1024 * 1024)
|
|
||||||
|
|
||||||
layout = QtWidgets.QVBoxLayout()
|
|
||||||
|
|
||||||
message = (
|
|
||||||
f"Incoming transfer request from {sender_ip}\n\n"
|
|
||||||
f"Files: {file_count}\n"
|
|
||||||
f"Total size: {size_mb:.2f} MB\n\n"
|
|
||||||
"Do you want to accept?"
|
|
||||||
)
|
|
||||||
|
|
||||||
label = QtWidgets.QLabel(message)
|
|
||||||
layout.addWidget(label)
|
|
||||||
|
|
||||||
button_box = QtWidgets.QDialogButtonBox(
|
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Yes | QtWidgets.QDialogButtonBox.StandardButton.No
|
|
||||||
)
|
|
||||||
button_box.accepted.connect(self.accept)
|
|
||||||
button_box.rejected.connect(self.reject)
|
|
||||||
|
|
||||||
layout.addWidget(button_box)
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QtWidgets.QMainWindow):
|
class MainWindow(QtWidgets.QMainWindow):
|
||||||
show_menu_signal = QtCore.Signal()
|
show_menu_signal = QtCore.Signal()
|
||||||
|
|
||||||
def __init__(self, dukto_handler, restart=False, no_quit=False, super_menu=True):
|
def __init__(self, restart=False, no_quit=False, super_menu=True):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
flags = (
|
flags = (
|
||||||
@@ -374,11 +344,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
self.setMask(mask)
|
self.setMask(mask)
|
||||||
|
|
||||||
self.super_menu = super_menu
|
self.super_menu = super_menu
|
||||||
self.dukto_handler = dukto_handler
|
|
||||||
self.dukto_handler.on_receive_request = self.handle_receive_request
|
|
||||||
|
|
||||||
self.receive_confirmation_event = threading.Event()
|
|
||||||
self.receive_confirmation_result = [False]
|
|
||||||
|
|
||||||
self.tray = QtWidgets.QSystemTrayIcon(self)
|
self.tray = QtWidgets.QSystemTrayIcon(self)
|
||||||
self.tray.setIcon(QtGui.QIcon(str(ASSET)))
|
self.tray.setIcon(QtGui.QIcon(str(ASSET)))
|
||||||
@@ -552,30 +517,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
elif status == "FAILED":
|
elif status == "FAILED":
|
||||||
QtWidgets.QMessageBox.critical(self, "Update Failed", message)
|
QtWidgets.QMessageBox.critical(self, "Update Failed", message)
|
||||||
|
|
||||||
@QtCore.Slot(str, int, int)
|
|
||||||
def show_receive_dialog(self, sender_ip, file_count, total_size):
|
|
||||||
dialog = ReceiveConfirmationDialog(sender_ip, file_count, total_size, self)
|
|
||||||
result = dialog.exec()
|
|
||||||
|
|
||||||
self.receive_confirmation_result[0] = (result == QtWidgets.QDialog.Accepted)
|
|
||||||
self.receive_confirmation_event.set()
|
|
||||||
|
|
||||||
def handle_receive_request(self, sender_ip, file_count, total_size) -> bool:
|
|
||||||
self.receive_confirmation_event.clear()
|
|
||||||
|
|
||||||
QtCore.QMetaObject.invokeMethod(
|
|
||||||
self, "show_receive_dialog", QtCore.Qt.QueuedConnection, #type: ignore
|
|
||||||
QtCore.Q_ARG(str, sender_ip),
|
|
||||||
QtCore.Q_ARG(int, file_count),
|
|
||||||
QtCore.Q_ARG(int, total_size),
|
|
||||||
)
|
|
||||||
|
|
||||||
self.receive_confirmation_event.wait()
|
|
||||||
return self.receive_confirmation_result[0]
|
|
||||||
|
|
||||||
def restart_application(self):
|
def restart_application(self):
|
||||||
presence.end()
|
presence.end()
|
||||||
self.dukto_handler.shutdown()
|
|
||||||
|
|
||||||
args = [sys.executable] + sys.argv
|
args = [sys.executable] + sys.argv
|
||||||
|
|
||||||
@@ -591,16 +534,9 @@ def main():
|
|||||||
restart = "--restart" in sys.argv
|
restart = "--restart" in sys.argv
|
||||||
no_quit = "--no-quit" in sys.argv
|
no_quit = "--no-quit" in sys.argv
|
||||||
super_menu = not "--no-super" in sys.argv
|
super_menu = not "--no-super" in sys.argv
|
||||||
|
pet = MainWindow(restart=restart, no_quit=no_quit, super_menu=super_menu)
|
||||||
dukto_handler = DuktoProtocol()
|
|
||||||
|
|
||||||
pet = MainWindow(dukto_handler=dukto_handler, restart=restart, no_quit=no_quit, super_menu=super_menu)
|
|
||||||
|
|
||||||
presence.start()
|
presence.start()
|
||||||
|
|
||||||
dukto_handler.initialize()
|
|
||||||
dukto_handler.say_hello()
|
|
||||||
|
|
||||||
# bottom right corner
|
# bottom right corner
|
||||||
screen_geometry = app.primaryScreen().availableGeometry()
|
screen_geometry = app.primaryScreen().availableGeometry()
|
||||||
pet_geometry = pet.frameGeometry()
|
pet_geometry = pet.frameGeometry()
|
||||||
@@ -611,7 +547,6 @@ def main():
|
|||||||
pet.show()
|
pet.show()
|
||||||
|
|
||||||
app.aboutToQuit.connect(presence.end)
|
app.aboutToQuit.connect(presence.end)
|
||||||
app.aboutToQuit.connect(dukto_handler.shutdown)
|
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user