246 lines
7.7 KiB
Python
246 lines
7.7 KiB
Python
import logging
|
|
|
|
import requests
|
|
|
|
from PyQt6 import QtCore
|
|
|
|
from .listener import Listener
|
|
from .models import (
|
|
GotifyApplicationModel,
|
|
GotifyErrorModel,
|
|
GotifyHealthModel,
|
|
GotifyMessageModel,
|
|
GotifyPagedMessagesModel,
|
|
GotifyPagingModel,
|
|
GotifyVersionModel,
|
|
)
|
|
|
|
logger = logging.getLogger("gotify-tray")
|
|
|
|
|
|
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)
|
|
|
|
def update_auth(self, url: str | None = None, token: str | None = None):
|
|
if url:
|
|
self.url = url
|
|
if token:
|
|
self.token = token
|
|
self.session.headers.update({"X-Gotify-Key": token})
|
|
|
|
def _get(self, endpoint: str = "/", **kwargs) -> requests.Response:
|
|
return self.session.get(self.url + endpoint, **kwargs)
|
|
|
|
def _post(self, endpoint: str = "/", **kwargs) -> requests.Response:
|
|
return self.session.post(self.url + endpoint, **kwargs)
|
|
|
|
def _put(self, endpoint: str = "/", **kwargs) -> requests.Response:
|
|
return self.session.put(self.url + endpoint, **kwargs)
|
|
|
|
def _delete(self, endpoint: str = "/", **kwargs) -> requests.Response:
|
|
return self.session.delete(self.url + endpoint, **kwargs)
|
|
|
|
|
|
# For sending messages
|
|
|
|
|
|
class GotifyApplication(GotifySession):
|
|
def push(
|
|
self, title: str = "", message: str = "", priority: int = 0, extras: dict | None = None
|
|
) -> GotifyMessageModel | GotifyErrorModel:
|
|
response = self._post(
|
|
"/message",
|
|
json={
|
|
"title": title,
|
|
"message": message,
|
|
"priority": priority,
|
|
"extras": extras,
|
|
},
|
|
)
|
|
return (
|
|
GotifyMessageModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
|
|
|
|
# For everything else
|
|
|
|
|
|
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
|
|
"""
|
|
|
|
def get_applications(self) -> list[GotifyApplicationModel] | GotifyErrorModel:
|
|
response = self._get("/application")
|
|
return (
|
|
[GotifyApplicationModel(x) for x in response.json()]
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
|
|
def create_application(
|
|
self, name: str, description: str = ""
|
|
) -> GotifyApplicationModel | GotifyErrorModel:
|
|
response = self._post(
|
|
"/application", json={"name": name, "description": description}
|
|
)
|
|
return (
|
|
GotifyApplicationModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
|
|
def update_application(
|
|
self, application_id: int, name: str, description: str = ""
|
|
) -> GotifyApplicationModel | GotifyErrorModel:
|
|
response = self._put(
|
|
f"/application/{application_id}",
|
|
json={"name": name, "description": description},
|
|
)
|
|
return (
|
|
GotifyApplicationModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
|
|
def delete_application(self, application_id: int) -> None | GotifyErrorModel:
|
|
response = self._delete(f"/application/{application_id}")
|
|
return None if response.ok else GotifyErrorModel(response)
|
|
|
|
def upload_application_image(
|
|
self, application_id: int, img_path: str
|
|
) -> GotifyApplicationModel | GotifyErrorModel | None:
|
|
try:
|
|
with open(img_path, "rb") as f:
|
|
response = self._post(
|
|
f"/application/{application_id}/image", files={"file": f}
|
|
)
|
|
return (
|
|
GotifyApplicationModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
except FileNotFoundError:
|
|
logger.error(
|
|
f"GotifyClient.upload_application_image: image '{img_path}' not found."
|
|
)
|
|
return None
|
|
|
|
def delete_application_image(self, application_id: int) -> None | GotifyErrorModel:
|
|
response = self._delete(f"/application/{application_id}/image")
|
|
return None if response.ok else GotifyErrorModel(response)
|
|
|
|
"""
|
|
Message
|
|
"""
|
|
|
|
def get_application_messages(
|
|
self, application_id: int, limit: int = 100, since: int | None = None
|
|
) -> GotifyPagedMessagesModel | GotifyErrorModel:
|
|
response = self._get(
|
|
f"/application/{application_id}/message",
|
|
params={"limit": limit, "since": since},
|
|
)
|
|
if not response.ok:
|
|
return GotifyErrorModel(response)
|
|
j = response.json()
|
|
return GotifyPagedMessagesModel(
|
|
messages=[GotifyMessageModel(m) for m in j["messages"]],
|
|
paging=GotifyPagingModel(j["paging"]),
|
|
)
|
|
|
|
def delete_application_messages(self, application_id: int) -> None | GotifyErrorModel:
|
|
response = self._delete(f"/application/{application_id}/message")
|
|
return None if response.ok else GotifyErrorModel(response)
|
|
|
|
def get_messages(
|
|
self, limit: int = 100, since: int | None = None
|
|
) -> GotifyPagedMessagesModel | GotifyErrorModel:
|
|
response = self._get("/message", params={"limit": limit, "since": since})
|
|
if not response.ok:
|
|
return GotifyErrorModel(response)
|
|
j = response.json()
|
|
return GotifyPagedMessagesModel(
|
|
messages=[GotifyMessageModel(m) for m in j["messages"]],
|
|
paging=GotifyPagingModel(j["paging"]),
|
|
)
|
|
|
|
def delete_messages(self) -> None | GotifyErrorModel:
|
|
response = self._delete("/message")
|
|
return None if response.ok else GotifyErrorModel(response)
|
|
|
|
def delete_message(self, message_id: int) -> None | GotifyErrorModel:
|
|
response = self._delete(f"/message/{message_id}")
|
|
return None if response.ok else GotifyErrorModel(response)
|
|
|
|
def listen(self):
|
|
self.listener.start()
|
|
|
|
def reconnect(self):
|
|
self.listener.reconnect()
|
|
|
|
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):
|
|
self.listener.close()
|
|
|
|
def is_listening(self) -> bool:
|
|
return self.listener.is_connected()
|
|
|
|
def reset_wait_time(self):
|
|
self.listener.reset_wait_time()
|
|
|
|
"""
|
|
Health
|
|
"""
|
|
|
|
def health(self) -> GotifyHealthModel | GotifyErrorModel:
|
|
response = self._get("/health")
|
|
return (
|
|
GotifyHealthModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|
|
|
|
"""
|
|
Version
|
|
"""
|
|
|
|
def version(self) -> GotifyVersionModel | GotifyErrorModel:
|
|
response = self._get("/version")
|
|
return (
|
|
GotifyVersionModel(response.json())
|
|
if response.ok
|
|
else GotifyErrorModel(response)
|
|
)
|