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.
This commit is contained in:
@@ -24,3 +24,6 @@ post_commit_hooks = []
|
|||||||
filename = "src/komgapi/__init__.py"
|
filename = "src/komgapi/__init__.py"
|
||||||
[[tool.bumpversion.files]]
|
[[tool.bumpversion.files]]
|
||||||
filename = "pyproject.toml"
|
filename = "pyproject.toml"
|
||||||
|
[[tool.bumpversion.files]]
|
||||||
|
filename = ".version"
|
||||||
|
|
||||||
|
|||||||
34
.gitea/ISSUE_TEMPLATE/bug.yml
Normal file
34
.gitea/ISSUE_TEMPLATE/bug.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Report a bug in this project
|
||||||
|
labels:
|
||||||
|
- kind/bug
|
||||||
|
- triage
|
||||||
|
body:
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: bug
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: |
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
What did you expect to happen? What happened instead?
|
||||||
|
Include screenshots if applicable.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: |
|
||||||
|
A clear and concise description of how to reproduce the bug.
|
||||||
|
Include steps, code snippets, or screenshots if applicable.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: additional-info
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: |
|
||||||
|
Add any other context or screenshots about the bug here.
|
||||||
|
|
||||||
|
|
||||||
23
.gitea/ISSUE_TEMPLATE/feature.yml
Normal file
23
.gitea/ISSUE_TEMPLATE/feature.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Suggest an idea for this project
|
||||||
|
labels:
|
||||||
|
- kind/feature
|
||||||
|
- triage
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: feature
|
||||||
|
attributes:
|
||||||
|
label: Describe the feature
|
||||||
|
description: |
|
||||||
|
A clear and concise description of what the feature is.
|
||||||
|
What is the problem it solves? What are you trying to accomplish?
|
||||||
|
Include screenshots if applicable.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: additional-info
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: |
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
88
.gitea/ISSUE_TEMPLATE/workflows/release.yml
Normal file
88
.gitea/ISSUE_TEMPLATE/workflows/release.yml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_notes:
|
||||||
|
description: Release notes (use \n for newlines)
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
github_release:
|
||||||
|
description: 'Create Gitea Release'
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
bump:
|
||||||
|
description: 'Bump type'
|
||||||
|
required: true
|
||||||
|
default: 'patch'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- 'major'
|
||||||
|
- 'minor'
|
||||||
|
- 'patch'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
- name: Set up Python
|
||||||
|
run: uv python install
|
||||||
|
- name: Set Git identity
|
||||||
|
run: |
|
||||||
|
git config user.name "Gitea CI"
|
||||||
|
git config user.email "ci@git.theprivateserver.de"
|
||||||
|
- name: Bump version
|
||||||
|
id: bump
|
||||||
|
run: |
|
||||||
|
uv tool install bump-my-version
|
||||||
|
uv tool run bump-my-version bump ${{ github.event.inputs.bump }}
|
||||||
|
# echo the version to github env, the version is shown by using uv tool run bump-my-version show current_version
|
||||||
|
echo "VERSION<<EOF" >> $GITHUB_ENV
|
||||||
|
echo "$(uv tool run bump-my-version show current_version)" >> $GITHUB_ENV
|
||||||
|
echo "EOF" >> $GITHUB_ENV
|
||||||
|
- name: Push changes
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: ${{ github.ref }}
|
||||||
|
|
||||||
|
- name: Add release notes to environment
|
||||||
|
id: add_release_notes
|
||||||
|
run: |
|
||||||
|
echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV
|
||||||
|
echo "${{ github.event.inputs.release_notes }}" >> $GITHUB_ENV
|
||||||
|
echo "EOF" >> $GITHUB_ENV
|
||||||
|
- name: Build package
|
||||||
|
run: uv build
|
||||||
|
- name: Publish package
|
||||||
|
env:
|
||||||
|
USERNAME: ${{ github.repository_owner }}
|
||||||
|
run: uv publish --publish-url https://git.theprivateserver.de/api/packages/$USERNAME/pypi/ -t ${{ secrets.TOKEN }}
|
||||||
|
- name: Generate changelog
|
||||||
|
id: changelog
|
||||||
|
uses: metcalfc/changelog-generator@v4.6.2
|
||||||
|
with:
|
||||||
|
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Get the changelog
|
||||||
|
run: |
|
||||||
|
cat << "EOF"
|
||||||
|
${{ steps.changelog.outputs.changelog }}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
id: create_release
|
||||||
|
if: ${{ github.event.inputs.github_release == 'true' }}
|
||||||
|
uses: softprops/action-gh-release@master
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.VERSION }}
|
||||||
|
release_name: Release ${{ env.VERSION }}
|
||||||
|
body: ${{ steps.changelog.outputs.changelog }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
make_latest: true
|
||||||
|
files: |
|
||||||
|
dist/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
@@ -8,7 +8,9 @@ authors = [
|
|||||||
]
|
]
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"httpx>=0.28.1",
|
||||||
"komconfig",
|
"komconfig",
|
||||||
|
"loguru>=0.7.3",
|
||||||
"typing-extensions>=4.12.2",
|
"typing-extensions>=4.12.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -17,6 +19,9 @@ requires = ["hatchling"]
|
|||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
"komconfig",
|
||||||
|
]
|
||||||
test = [
|
test = [
|
||||||
"pytest>=8.3.4",
|
"pytest>=8.3.4",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import requests
|
import httpx
|
||||||
from komgapi.errors import KomgaError, LoginError, ResultErrror
|
from httpx_retries import Retry, RetryTransport
|
||||||
|
from komgapi.errors import KomgaError, ResultErrror
|
||||||
from typing import Any, Union
|
from typing import Any, Union
|
||||||
from limit import limit
|
from limit import limit # type:ignore
|
||||||
|
|
||||||
import loguru
|
import loguru
|
||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
log = loguru.logger
|
log = loguru.logger
|
||||||
log.remove()
|
log.remove()
|
||||||
@@ -13,29 +15,37 @@ log.add(sys.stdout, level="INFO")
|
|||||||
|
|
||||||
|
|
||||||
class BaseAPI:
|
class BaseAPI:
|
||||||
def __init__(self, username, password, url, timeout=20, api_version=1) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
username: str,
|
||||||
|
password: str,
|
||||||
|
url: str,
|
||||||
|
timeout: int = 20,
|
||||||
|
api_version: int = 1,
|
||||||
|
) -> None:
|
||||||
self._username = username
|
self._username = username
|
||||||
self._password = password
|
self._password = password
|
||||||
self.url = url + f"api/v{api_version}/"
|
self.url = url + f"api/v{api_version}/"
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
self.headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
def setParams(self, locals: dict) -> dict:
|
def setParams(self, locals: dict[Any, Any]) -> dict[Any, Any]:
|
||||||
return {
|
return {
|
||||||
param_name: param
|
param_name: param
|
||||||
for param_name, param in locals.items()
|
for param_name, param in locals.items()
|
||||||
if param is not None and param_name not in ["self", "series_idurl"]
|
if param is not None
|
||||||
|
and param_name not in ["self", "series_idurl", "query", "url"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_connection(self):
|
def test_connection(self):
|
||||||
"""Test the connection to the server.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if the connection is successful, False otherwise.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
requests.get(self.url, timeout=self.timeout)
|
with httpx.Client(timeout=self.timeout) as client:
|
||||||
|
client.get(self.url, headers=self.headers)
|
||||||
return True
|
return True
|
||||||
except requests.exceptions.RequestException:
|
except httpx.RequestError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def overwriteVersion(self, version: int):
|
def overwriteVersion(self, version: int):
|
||||||
@@ -43,126 +53,123 @@ class BaseAPI:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
@limit(1, 1)
|
@limit(1, 1)
|
||||||
def getRequest(self, url, params: Union[dict, None] = None) -> Any:
|
def getRequest(self, url: str, params: Union[dict[Any, Any], None] = None) -> Any:
|
||||||
if params is None:
|
if params is None:
|
||||||
params = {}
|
params = {}
|
||||||
try:
|
try:
|
||||||
response = requests.get(
|
with httpx.Client(
|
||||||
url,
|
|
||||||
auth=(self._username, self._password),
|
|
||||||
params=params,
|
|
||||||
timeout=self.timeout,
|
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:
|
if response.status_code != 200:
|
||||||
self.getRequest(url, params)
|
return self.getRequest(url, params)
|
||||||
# print(response.content)
|
|
||||||
log.debug(f"Response: {response.content}")
|
|
||||||
return response.json()
|
return response.json()
|
||||||
except ConnectionError as e:
|
except httpx.ConnectError as e:
|
||||||
message = f"Connection Error: {e}"
|
raise KomgaError(f"Connection Error: {e}") from e
|
||||||
raise KomgaError(message) from e
|
except httpx.TimeoutException as e:
|
||||||
except requests.exceptions.Timeout as e:
|
|
||||||
raise KomgaError(f"Timeout Error: {e}") from e
|
raise KomgaError(f"Timeout Error: {e}") from e
|
||||||
|
|
||||||
def postRequest(self, url, data: Union[dict, None] = None, body: dict = None):
|
def postRequest(
|
||||||
|
self,
|
||||||
|
url: str,
|
||||||
|
data: Union[dict[Any, Any], None] = None,
|
||||||
|
body: Union[dict[Any, Any], None] = None,
|
||||||
|
):
|
||||||
if data is None:
|
if data is None:
|
||||||
data = {}
|
data = {}
|
||||||
try:
|
try:
|
||||||
if body is not None:
|
with httpx.Client(
|
||||||
response = requests.post(
|
timeout=self.timeout, auth=(self._username, self._password), transport=RetryTransport(retry=Retry(total=5, backoff_factor=0.5))
|
||||||
|
) as client:
|
||||||
|
response = client.post(
|
||||||
url,
|
url,
|
||||||
auth=(self._username, self._password),
|
|
||||||
json=body,
|
|
||||||
params=data,
|
params=data,
|
||||||
timeout=self.timeout,
|
json=body if body is not None else {},
|
||||||
|
headers=self.headers,
|
||||||
)
|
)
|
||||||
else:
|
log.debug(
|
||||||
response = requests.post(
|
"POST request to {} with data: {}, json: {}",
|
||||||
url,
|
url,
|
||||||
auth=(self._username, self._password),
|
json.dumps(data),
|
||||||
json=data,
|
json.dumps(body),
|
||||||
timeout=self.timeout,
|
|
||||||
params=data,
|
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
status_code = response.status_code
|
status_code = response.status_code
|
||||||
if status_code == 202:
|
if status_code == 202:
|
||||||
log.debug(f"Response: {response}")
|
return None
|
||||||
# raise ResultErrror(f"Result Error: {response}")
|
|
||||||
elif status_code == 200:
|
elif status_code == 200:
|
||||||
log.debug(f"Response: {response}")
|
|
||||||
return response.json()
|
return response.json()
|
||||||
else:
|
else:
|
||||||
log.debug(f"Response: {response}")
|
|
||||||
raise ResultErrror(f"Result Error: {response.content}")
|
raise ResultErrror(f"Result Error: {response.content}")
|
||||||
except ConnectionError as e:
|
except httpx.ConnectError as e:
|
||||||
message = f"Connection Error: {e}"
|
raise KomgaError(f"Connection Error: {e}") from e
|
||||||
raise KomgaError(message) from e
|
except httpx.TimeoutException as e:
|
||||||
except requests.exceptions.Timeout as e:
|
|
||||||
raise KomgaError(f"Timeout Error: {e}") from e
|
raise KomgaError(f"Timeout Error: {e}") from e
|
||||||
|
|
||||||
def patchRequest(self, url, data: Union[dict, None] = None):
|
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:
|
if data is None:
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print("patching data", data, url)
|
log.debug("PATCH request to {} with data: {}", url, json.dumps(data))
|
||||||
response = requests.patch(
|
|
||||||
url,
|
with httpx.Client(
|
||||||
auth=(self._username, self._password),
|
|
||||||
json=data,
|
|
||||||
timeout=self.timeout,
|
timeout=self.timeout,
|
||||||
)
|
auth=(self._username, self._password),
|
||||||
|
headers=self.headers,
|
||||||
|
) as client:
|
||||||
|
response = client.patch(url, json=data)
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
log.debug(
|
|
||||||
f"Response: {response}, {response.status_code}, {response.content}"
|
if response.status_code == 204:
|
||||||
)
|
return None
|
||||||
print(response.status_code, response.content)
|
|
||||||
if response.status_code != 204:
|
return response.json() if response.content else None
|
||||||
raise ResultErrror(f"Result Error: {response.json()}")
|
|
||||||
except ConnectionError as e:
|
except httpx.ConnectError as e:
|
||||||
message = f"Connection Error: {e}"
|
log.error("Connection error during PATCH to {}: {}", url, str(e))
|
||||||
raise KomgaError(message) from e
|
raise KomgaError(f"Connection Error: {e}") from e
|
||||||
except requests.exceptions.Timeout as e:
|
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
|
log.error("Timeout during PATCH to {}: {}", url, str(e))
|
||||||
raise KomgaError(f"Timeout Error: {e}") from e
|
raise KomgaError(f"Timeout Error: {e}") from e
|
||||||
|
|
||||||
def putRequest(self, url, data: Union[dict, None] = None):
|
except httpx.HTTPStatusError as e:
|
||||||
if data is None:
|
log.error("HTTP error during PATCH to {}: {}", url, e.response.text)
|
||||||
data = {}
|
raise ResultErrror(f"Result Error: {e.response.text}") from e
|
||||||
try:
|
|
||||||
response = requests.put(
|
|
||||||
url,
|
|
||||||
auth=(self._username, self._password),
|
|
||||||
json=data,
|
|
||||||
timeout=self.timeout,
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
except ConnectionError as e:
|
|
||||||
message = f"Connection Error: {e}"
|
|
||||||
raise KomgaError(message) from e
|
|
||||||
except requests.exceptions.Timeout as e:
|
|
||||||
raise KomgaError(f"Timeout Error: {e}") from e
|
|
||||||
|
|
||||||
def deleteRequest(self, url):
|
def deleteRequest(self, url: str):
|
||||||
try:
|
try:
|
||||||
response = requests.delete(
|
with httpx.Client(
|
||||||
url, auth=(self._username, self._password), timeout=self.timeout
|
timeout=self.timeout, auth=(self._username, self._password)
|
||||||
)
|
) as client:
|
||||||
|
response = client.delete(url, headers=self.headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.json()
|
return response.json()
|
||||||
except ConnectionError as e:
|
except httpx.ConnectError as e:
|
||||||
message = f"Connection Error: {e}"
|
raise KomgaError(f"Connection Error: {e}") from e
|
||||||
raise KomgaError(message) from e
|
except httpx.TimeoutException as e:
|
||||||
except requests.exceptions.Timeout as e:
|
|
||||||
raise KomgaError(f"Timeout Error: {e}") from e
|
raise KomgaError(f"Timeout Error: {e}") from e
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_env(cls):
|
def from_env(cls):
|
||||||
"""Create a KOMGA API object from environment variables.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
KOMGAPI_REST: The KOMGA API object.
|
|
||||||
"""
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class BookController(BaseAPI):
|
|||||||
def __init__(self, username, password, url, timeout=20) -> None:
|
def __init__(self, username, password, url, timeout=20) -> None:
|
||||||
super().__init__(username, password, url, timeout)
|
super().__init__(username, password, url, timeout)
|
||||||
|
|
||||||
|
@typing_extensions.deprecated("This function is deprecated.")
|
||||||
def getBooks(
|
def getBooks(
|
||||||
self,
|
self,
|
||||||
search_string: str = None,
|
search_string: str = None,
|
||||||
@@ -53,6 +54,17 @@ class BookController(BaseAPI):
|
|||||||
ret.append(Book(**book))
|
ret.append(Book(**book))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def listBooks(
|
||||||
|
self, query: dict[str, Any] = None, unpaged: bool = True
|
||||||
|
) -> List[Book]:
|
||||||
|
url = self.url + "books/list"
|
||||||
|
if query is None:
|
||||||
|
query = {}
|
||||||
|
params = locals()
|
||||||
|
params = self.setParams(params)
|
||||||
|
data = self.postRequest(url, params, query)
|
||||||
|
return [Book(**book) for book in data["content"]]
|
||||||
|
|
||||||
def getBook(self, book_id: str) -> Book:
|
def getBook(self, book_id: str) -> Book:
|
||||||
"""Get a specific book.
|
"""Get a specific book.
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import subprocess
|
|||||||
import requests
|
import requests
|
||||||
import typing_extensions
|
import typing_extensions
|
||||||
from typing import List, Optional, Dict, Any, Union
|
from typing import List, Optional, Dict, Any, Union
|
||||||
|
import json
|
||||||
from komgapi.schemas import * # Progress, Series
|
from komgapi.schemas import Series, Book, Collection, Thumbnail
|
||||||
|
|
||||||
import loguru
|
import loguru
|
||||||
import sys
|
import sys
|
||||||
@@ -86,6 +86,10 @@ class SeriesController(BaseAPI):
|
|||||||
data = self.postRequest(url)
|
data = self.postRequest(url)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
# mark as pending deprecation
|
||||||
|
@typing_extensions.deprecated(
|
||||||
|
"This function will be deprecated soon. Switch to BookController.listBooks()"
|
||||||
|
)
|
||||||
def getSeriesBooks(
|
def getSeriesBooks(
|
||||||
self,
|
self,
|
||||||
series_id: str,
|
series_id: str,
|
||||||
@@ -240,8 +244,11 @@ class SeriesController(BaseAPI):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
url = self.url + f"series/{series_id}/metadata"
|
url = self.url + f"series/{series_id}/metadata"
|
||||||
|
# change metadata to a json string
|
||||||
|
# changed_metadata = json.dumps(changed_metadata)
|
||||||
|
log.info("Changed metadata: {}", changed_metadata)
|
||||||
|
|
||||||
data = self.patchRequest(url, changed_metadata)
|
data = self.patchRequest(url, changed_metadata)
|
||||||
log.debug("Changed metadata: {}", data)
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|||||||
@@ -87,3 +87,40 @@ class KOMGAPI_REST:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Book controller
|
# Book controller
|
||||||
|
def seriesList(self) -> list[str]:
|
||||||
|
"""Get the list of books from the server.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: The list of books.
|
||||||
|
"""
|
||||||
|
data = []
|
||||||
|
series = self.series_controller.getAllSeries()
|
||||||
|
for serie in series:
|
||||||
|
data.append(serie.name)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def getSeries(self, seriesName: str) -> bool:
|
||||||
|
"""Get the series from the server.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
seriesName (str): The name of the series.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the series is found, False otherwise.
|
||||||
|
"""
|
||||||
|
series = self.series_controller.getAllSeries(
|
||||||
|
body={"condition": {"title": {"operator": "contains", "value": seriesName}}}
|
||||||
|
)
|
||||||
|
if len(series) == 1:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
for serie in series:
|
||||||
|
if serie.name.strip().lower() == seriesName.strip().lower():
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
# for serie in series:
|
||||||
|
# print(f"series: {serie}")
|
||||||
|
# if serie.name.strip().lower() == seriesName.strip().lower():
|
||||||
|
# return True
|
||||||
|
# return False
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Library:
|
class Library:
|
||||||
|
"""Library class to represent a library in the API."""
|
||||||
|
|
||||||
id: str
|
id: str
|
||||||
name: str
|
name: str
|
||||||
root: str
|
root: str
|
||||||
|
|||||||
@@ -7,21 +7,25 @@ from .Metadata import Metadata
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Series:
|
class Series:
|
||||||
id: str = None
|
"""
|
||||||
libraryId: str = None
|
A class representing a series in the KOMGA API.
|
||||||
name: str = None
|
"""
|
||||||
url: str = None
|
|
||||||
created: str = None
|
id: Optional[str] = None
|
||||||
lastModified: str = None
|
libraryId: Optional[str] = None
|
||||||
fileLastModified: str = None
|
name: Optional[str] = None
|
||||||
booksCount: int = 0
|
url: Optional[str] = None
|
||||||
booksReadCount: int = None
|
created: Optional[str] = None
|
||||||
booksUnreadCount: int = None
|
lastModified: Optional[str] = None
|
||||||
booksInProgressCount: int = None
|
fileLastModified: Optional[str] = None
|
||||||
metadata: Metadata = None
|
booksCount: Optional[int] = 0
|
||||||
booksMetadata: BooksMetadata = None
|
booksReadCount: Optional[int] = None
|
||||||
deleted: bool = None
|
booksUnreadCount: Optional[int] = None
|
||||||
oneshot: bool = None
|
booksInProgressCount: Optional[int] = None
|
||||||
|
metadata: Optional[Metadata] = None
|
||||||
|
booksMetadata: Optional[BooksMetadata] = None
|
||||||
|
deleted: Optional[bool] = None
|
||||||
|
oneshot: Optional[bool] = None
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if self.metadata is None:
|
if self.metadata is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user