Files
komgAPI/src/komgapi/endpoints/baseapi.py
WorldTeacher 5a0502b748 Add issue templates, enhance API functionality, and update dependencies
- Introduced bug report and feature request templates for better issue tracking.
- Added release workflow for automated versioning and package publishing.
- Updated dependencies in `pyproject.toml` for improved functionality.
- Refactored API endpoints to use `httpx` for better performance and error handling.
- Added new methods in `BookController` and `KOMGAPI_REST` for enhanced book and series management.
- Updated schemas to include optional fields for better data handling.
2025-05-23 16:42:33 +02:00

180 lines
5.8 KiB
Python

import httpx
from httpx_retries import Retry, RetryTransport
from komgapi.errors import KomgaError, ResultErrror
from typing import Any, Union
from limit import limit # type:ignore
import loguru
import sys
import json
log = loguru.logger
log.remove()
log.add("logs/komga_api.log", rotation="1 week", retention="1 month")
log.add(sys.stdout, level="INFO")
class BaseAPI:
def __init__(
self,
username: str,
password: str,
url: str,
timeout: int = 20,
api_version: int = 1,
) -> None:
self._username = username
self._password = password
self.url = url + f"api/v{api_version}/"
self.timeout = timeout
self.headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
def setParams(self, locals: dict[Any, Any]) -> dict[Any, Any]:
return {
param_name: param
for param_name, param in locals.items()
if param is not None
and param_name not in ["self", "series_idurl", "query", "url"]
}
def test_connection(self):
try:
with httpx.Client(timeout=self.timeout) as client:
client.get(self.url, headers=self.headers)
return True
except httpx.RequestError:
return False
def overwriteVersion(self, version: int):
self.url = self.url.replace("api/v1/", f"api/v{version}/")
return self
@limit(1, 1)
def getRequest(self, url: str, params: Union[dict[Any, Any], None] = None) -> Any:
if params is None:
params = {}
try:
with httpx.Client(
timeout=self.timeout,
auth=(self._username, self._password),
transport=RetryTransport(retry=Retry(total=5, backoff_factor=0.5)),
) as client:
response = client.get(url, params=params, headers=self.headers)
if response.status_code != 200:
return self.getRequest(url, params)
return response.json()
except httpx.ConnectError as e:
raise KomgaError(f"Connection Error: {e}") from e
except httpx.TimeoutException as e:
raise KomgaError(f"Timeout Error: {e}") from e
def postRequest(
self,
url: str,
data: Union[dict[Any, Any], None] = None,
body: Union[dict[Any, Any], None] = None,
):
if data is None:
data = {}
try:
with httpx.Client(
timeout=self.timeout, auth=(self._username, self._password), transport=RetryTransport(retry=Retry(total=5, backoff_factor=0.5))
) as client:
response = client.post(
url,
params=data,
json=body if body is not None else {},
headers=self.headers,
)
log.debug(
"POST request to {} with data: {}, json: {}",
url,
json.dumps(data),
json.dumps(body),
)
response.raise_for_status()
status_code = response.status_code
if status_code == 202:
return None
elif status_code == 200:
return response.json()
else:
raise ResultErrror(f"Result Error: {response.content}")
except httpx.ConnectError as e:
raise KomgaError(f"Connection Error: {e}") from e
except httpx.TimeoutException as e:
raise KomgaError(f"Timeout Error: {e}") from e
def patchRequest(self, url: str, data: Union[dict[Any, Any], None] = None):
"""Send PATCH request to API endpoint.
Args:
url (str): API endpoint URL
data (Union[dict[Any, Any], None]): Data to send in request body
Returns:
dict: JSON response from server
Raises:
KomgaError: For connection/timeout errors
ResultError: For invalid responses
"""
if data is None:
data = {}
try:
log.debug("PATCH request to {} with data: {}", url, json.dumps(data))
with httpx.Client(
timeout=self.timeout,
auth=(self._username, self._password),
headers=self.headers,
) as client:
response = client.patch(url, json=data)
response.raise_for_status()
if response.status_code == 204:
return None
return response.json() if response.content else None
except httpx.ConnectError as e:
log.error("Connection error during PATCH to {}: {}", url, str(e))
raise KomgaError(f"Connection Error: {e}") from e
except httpx.TimeoutException as e:
log.error("Timeout during PATCH to {}: {}", url, str(e))
raise KomgaError(f"Timeout Error: {e}") from e
except httpx.HTTPStatusError as e:
log.error("HTTP error during PATCH to {}: {}", url, e.response.text)
raise ResultErrror(f"Result Error: {e.response.text}") from e
def deleteRequest(self, url: str):
try:
with httpx.Client(
timeout=self.timeout, auth=(self._username, self._password)
) as client:
response = client.delete(url, headers=self.headers)
response.raise_for_status()
return response.json()
except httpx.ConnectError as e:
raise KomgaError(f"Connection Error: {e}") from e
except httpx.TimeoutException as e:
raise KomgaError(f"Timeout Error: {e}") from e
@classmethod
def from_env(cls):
import os
return cls(
os.environ["KOMGA_USERNAME"],
os.environ["KOMGA_PASSWORD"],
os.environ["KOMGA_URL"],
)