import json from dataclasses import dataclass from logging import getLogger from typing import Callable from typing import Union from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QJsonParseError, QJsonDocument from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply logger = getLogger("QtRequests") class QtRequestManager(QObject): data_ready = pyqtSignal(object) request = None request_active = None def __init__(self, type: str = "json", authorization_token: str = None): super(QtRequestManager, self).__init__() self.manager = QNetworkAccessManager() self.type = type self.authorization_token = authorization_token self.request_queue = [] def post(self, url: str, payload: dict, handle_func): if not self.request_active: request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self.request_active = RequestQueueItem(handle_func=handle_func) payload = json.dumps(payload).encode("utf-8") request.setHeader( QNetworkRequest.UserAgentHeader, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", ) if self.authorization_token is not None: request.setRawHeader( b"Authorization", self.authorization_token.encode() ) self.request = self.manager.post(request, payload) self.request.finished.connect(self.prepare_data) else: self.request_queue.append( RequestQueueItem( method="post", url=url, payload=payload, handle_func=handle_func ) ) def get(self, url: str, handle_func: Callable[[Union[dict, bytes]], None]): if not self.request_active: request = QNetworkRequest(QUrl(url)) request.setHeader( QNetworkRequest.UserAgentHeader, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", ) self.request_active = RequestQueueItem(handle_func=handle_func) self.request = self.manager.get(request) self.request.finished.connect(self.prepare_data) else: self.request_queue.append( RequestQueueItem(method="get", url=url, handle_func=handle_func) ) def prepare_data(self): # self.request_active = False data = {} if self.type == "json" else b"" if self.request: try: if self.request.error() == QNetworkReply.NoError: if self.type == "json": error = QJsonParseError() json_data = QJsonDocument.fromJson( self.request.readAll().data(), error ) if QJsonParseError.NoError == error.error: data = json.loads(json_data.toJson().data().decode()) else: logger.error(error.errorString()) else: data = self.request.readAll().data() except RuntimeError as e: logger.error(str(e)) self.request_active.handle_func(data) self.request.deleteLater() self.request_active = None if self.request_queue: if self.request_queue[0].method == "post": self.post( self.request_queue[0].url, self.request_queue[0].payload, self.request_queue[0].handle_func, ) else: self.get(self.request_queue[0].url, self.request_queue[0].handle_func) self.request_queue.pop(0) @dataclass class RequestQueueItem: method: str = None url: str = None handle_func: Callable[[Union[dict, bytes]], None] = None payload: dict = None