remove websocket-client dependency in favor of QWebSocket

This commit is contained in:
dries.k
2023-08-05 16:36:12 +02:00
parent 6b5434978b
commit db8bfc0f44
5 changed files with 94 additions and 126 deletions

View File

@@ -1,8 +1,9 @@
import logging
from typing import Callable
import requests
from PyQt6 import QtCore
from .listener import Listener
from .models import (
GotifyApplicationModel,
@@ -17,8 +18,9 @@ from .models import (
logger = logging.getLogger("gotify-tray")
class GotifySession(object):
class GotifySession(QtCore.QObject):
def __init__(self, url: str, token: str):
super(GotifySession, self).__init__()
self.session = requests.Session()
self.update_auth(url.rstrip("/"), token)
@@ -46,9 +48,6 @@ class GotifySession(object):
class GotifyApplication(GotifySession):
def __init__(self, url: str, application_token: str):
super(GotifyApplication, self).__init__(url, application_token)
def push(
self, title: str = "", message: str = "", priority: int = 0, extras: dict | None = None
) -> GotifyMessageModel | GotifyErrorModel:
@@ -72,6 +71,23 @@ class GotifyApplication(GotifySession):
class GotifyClient(GotifySession):
new_message = QtCore.pyqtSignal(GotifyMessageModel)
opened = QtCore.pyqtSignal()
closed = QtCore.pyqtSignal()
def __init__(self, url: str, client_token: str):
self.listener = Listener(url, client_token)
super(GotifyClient, self).__init__(url, client_token)
self.listener.opened.connect(self.opened.emit)
self.listener.closed.connect(self.closed.emit)
self.listener.new_message.connect(self.new_message.emit)
def update_auth(self, url: str | None = None, token: str | None = None):
super().update_auth(url, token)
self.listener.update_auth(url, token)
"""
Application
@@ -180,48 +196,26 @@ class GotifyClient(GotifySession):
response = self._delete(f"/message/{message_id}")
return None if response.ok else GotifyErrorModel(response)
def listen(
self,
opened_callback: (Callable[[], None]) | None = None,
closed_callback: Callable[[int, str], None] | None = None,
new_message_callback: Callable[[GotifyMessageModel], None] | None = None,
error_callback: Callable[[Exception], None] | None = None,
):
def dummy(*args):
...
self.listener = Listener(self.url, self.token)
self.listener.opened.connect(lambda: self.opened_callback(opened_callback))
self.listener.closed.connect(closed_callback or dummy)
self.listener.new_message.connect(new_message_callback or dummy)
self.listener.error.connect(error_callback or dummy)
def listen(self):
self.listener.start()
def opened_callback(self, user_callback: Callable[[], None] | None = None):
self.reset_wait_time()
if user_callback:
user_callback()
def reconnect(self):
if not self.is_listening():
self.listener.start()
self.listener.reconnect()
def stop_final(self):
self.listener.stop_final()
def quit(self):
"""Close the listener and disconnect from the closed signal so it doesn't get reopened
"""
try:
self.listener.closed.disconnect()
except TypeError:
logger.error(f"listener.closed was already disconnected.")
self.listener.close()
def stop(self, reset_wait: bool = False):
if reset_wait:
self.reset_wait_time()
self.listener.stop()
def stop(self):
self.listener.close()
def is_listening(self) -> bool:
return self.listener.running
def increase_wait_time(self):
self.listener.increase_wait_time()
def get_wait_time(self) -> int:
return self.listener.wait_time
return self.listener.is_connected()
def reset_wait_time(self):
self.listener.reset_wait_time()

View File

@@ -1,42 +1,52 @@
import json
import logging
import platform
import ssl
import websocket
from PyQt6 import QtCore
from PyQt6 import QtNetwork, QtWebSockets
from .models import GotifyMessageModel, GotifyErrorModel
from .models import GotifyMessageModel
logger = logging.getLogger("gotify-tray")
class Listener(QtCore.QThread):
class Listener(QtWebSockets.QWebSocket):
new_message = QtCore.pyqtSignal(GotifyMessageModel)
error = QtCore.pyqtSignal(Exception)
opened = QtCore.pyqtSignal()
closed = QtCore.pyqtSignal(int, str)
closed = QtCore.pyqtSignal()
def __init__(self, url: str, client_token: str):
super(Listener, self).__init__()
qurl = QtCore.QUrl(url.rstrip("/") + "/")
qurl.setScheme("wss" if qurl.scheme() == "https" else "ws")
qurl.setPath(qurl.path() + "stream")
qurl.setQuery(f"token={client_token}")
self.update_auth(url, client_token)
self.ws = websocket.WebSocketApp(
qurl.toString(),
on_message=self._on_message,
on_error=self._on_error,
on_open=self._on_open,
on_close=self._on_close,
)
self.connected.connect(self._on_connect)
self.disconnected.connect(self._on_disconnect)
self.error.connect(self._on_error)
self.textMessageReceived.connect(self._on_message)
self.wait_time = 0
self.reset_wait_time()
self.running = False
def update_auth(self, url: str, client_token: str):
self.qurl = QtCore.QUrl(url.rstrip("/") + "/")
self.qurl.setScheme("wss" if self.qurl.scheme() == "https" else "ws")
self.qurl.setPath(self.qurl.path() + "stream")
self.qurl.setQuery(f"token={client_token}")
def start(self):
logger.debug("Opening connection.")
self.open(self.qurl)
def stop(self):
logger.debug("Stopping listener.")
self.close()
def reconnect(self):
self.increase_wait_time()
QtCore.QTimer.singleShot(self.wait_time * 1000, self.start)
def is_connected(self) -> bool:
return self.state() == QtNetwork.QAbstractSocket.SocketState.ConnectedState
def reset_wait_time(self):
self.wait_time = 0
@@ -47,42 +57,17 @@ class Listener(QtCore.QThread):
else:
self.wait_time = min(self.wait_time * 2, 10 * 60)
def _on_message(self, ws: websocket.WebSocketApp, message: str):
def _on_connect(self):
logger.debug("Connection established.")
self.reset_wait_time()
self.opened.emit()
def _on_disconnect(self):
logger.debug(f"Connection was closed: {self.closeCode()}.")
self.closed.emit()
def _on_message(self, message: str):
self.new_message.emit(GotifyMessageModel(json.loads(message)))
def _on_error(self, ws: websocket.WebSocketApp, error: Exception):
logger.error(f"websocket error: {error}")
self.error.emit(error)
def _on_open(self, ws: websocket.WebSocketApp):
self.opened.emit()
self.reset_wait_time()
def _on_close(
self, ws: websocket.WebSocketApp, close_status_code: int, close_msg: str
):
self.closed.emit(close_status_code, close_msg)
def stop_final(self):
def dummy(*args):
...
self.ws.on_close = dummy
self.ws.close()
self.running = False
def stop(self):
logger.debug("Listener: stopping.")
self.ws.close()
self.running = False
def run(self):
self.running = True
try:
if platform.system() == "Darwin":
self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
else:
self.ws.run_forever()
finally:
logger.debug("Listener: stopped.")
self.running = False
def _on_error(self):
logger.error(f"Listener socker error: {self.errorString()}")