remove websocket-client dependency in favor of QWebSocket
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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()}")
|
||||
|
||||
Reference in New Issue
Block a user