aioaudiobookshelf 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aioaudiobookshelf might be problematic. Click here for more details.
- aioaudiobookshelf-0.1.3/PKG-INFO +120 -0
- aioaudiobookshelf-0.1.3/README.md +90 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/__init__.py +40 -3
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/__init__.py +3 -3
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/exceptions.py +4 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_login.py +4 -0
- aioaudiobookshelf-0.1.3/aioaudiobookshelf.egg-info/PKG-INFO +120 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/pyproject.toml +3 -3
- aioaudiobookshelf-0.1.2/PKG-INFO +0 -32
- aioaudiobookshelf-0.1.2/README.md +0 -2
- aioaudiobookshelf-0.1.2/aioaudiobookshelf.egg-info/PKG-INFO +0 -32
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/LICENSE +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/_base.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/authors.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/collections_.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/items.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/libraries.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/me.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/playlists.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/podcasts.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/series.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/session.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/helpers.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/__init__.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/audio.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/author.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/book.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_authors.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_collections.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_items.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_library.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_me.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_playlists.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_series.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_session.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/collection.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/events_socket.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/file.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/folder.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/library.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/media_progress.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/playlist.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/podcast.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/series.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/series_books.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/server.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/session.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/user.py +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/SOURCES.txt +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/dependency_links.txt +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/not-zip-safe +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/requires.txt +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/top_level.txt +0 -0
- {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/setup.cfg +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: aioaudiobookshelf
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Async library for Audiobookshelf
|
|
5
|
+
Author-email: Fabian Munkes <105975993+fmunkes@users.noreply.github.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Platform: any
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: aiohttp
|
|
15
|
+
Requires-Dist: mashumaro
|
|
16
|
+
Requires-Dist: python-socketio>=5.12
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: codespell==2.3.0; extra == "test"
|
|
19
|
+
Requires-Dist: isort==5.13.2; extra == "test"
|
|
20
|
+
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
21
|
+
Requires-Dist: pre-commit==4.0.1; extra == "test"
|
|
22
|
+
Requires-Dist: pre-commit-hooks==5.0.0; extra == "test"
|
|
23
|
+
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
24
|
+
Requires-Dist: pytest-aiohttp==1.0.5; extra == "test"
|
|
25
|
+
Requires-Dist: pytest-cov==5.0.0; extra == "test"
|
|
26
|
+
Requires-Dist: syrupy==4.8.1; extra == "test"
|
|
27
|
+
Requires-Dist: tomli==2.2.1; extra == "test"
|
|
28
|
+
Requires-Dist: ruff==0.9.2; extra == "test"
|
|
29
|
+
Requires-Dist: bumpver; extra == "test"
|
|
30
|
+
|
|
31
|
+
# aioaudiobookshelf
|
|
32
|
+
Async python library to interact with
|
|
33
|
+
[Audiobookshelf](https://github.com/advplyr/audiobookshelf) (ABS).
|
|
34
|
+
|
|
35
|
+
This lib's primary goal is to be used within the Audiobookshelf music provider
|
|
36
|
+
in Music Assistant, but it can be used independently. Calls to endpoints not
|
|
37
|
+
needed for the provider will be added over time.
|
|
38
|
+
|
|
39
|
+
Not all endpoints are yet implemented.
|
|
40
|
+
|
|
41
|
+
## Releases
|
|
42
|
+
Releases can be found on [pypi](https://pypi.org/project/aioaudiobookshelf/),
|
|
43
|
+
and are tagged.
|
|
44
|
+
|
|
45
|
+
## Basic usage
|
|
46
|
+
ABS has a rest api, documented
|
|
47
|
+
[here](https://api.audiobookshelf.org) and additionally uses socket.io, see
|
|
48
|
+
[here](https://api.audiobookshelf.org/#socket) for some event driven
|
|
49
|
+
functionality.
|
|
50
|
+
Accessibility to the endpoints is determined by the [user
|
|
51
|
+
types](https://api.audiobookshelf.org/#user), which may be `root, admin, user, guest`.
|
|
52
|
+
This lib is not tested with a `guest` user.
|
|
53
|
+
|
|
54
|
+
As of `0.1.2` this lib has two different clients, the `UserClient` and the
|
|
55
|
+
`SocketClient`. Admin endpoints are not yet implemented. The user client
|
|
56
|
+
handles calls to the Rest API, the socket client allows to subscribe to certain
|
|
57
|
+
events.
|
|
58
|
+
|
|
59
|
+
To authenticate the socket client, you always need the user's token, username
|
|
60
|
+
and password are not enough. The user client can be authenticated by username
|
|
61
|
+
and password, which yields the token.
|
|
62
|
+
|
|
63
|
+
Usage example:
|
|
64
|
+
```python
|
|
65
|
+
import asyncio
|
|
66
|
+
import logging
|
|
67
|
+
import os
|
|
68
|
+
|
|
69
|
+
import aiohttp
|
|
70
|
+
|
|
71
|
+
from aioaudiobookshelf import SessionConfiguration, get_user_client
|
|
72
|
+
from aioaudiobookshelf.schema.library import LibraryItemMinifiedBook, LibraryItemMinifiedPodcast
|
|
73
|
+
|
|
74
|
+
ABS_HOST = os.environ.get("ABS_HOST")
|
|
75
|
+
ABS_USER = os.environ.get("ABS_USER")
|
|
76
|
+
ABS_PASSWORD = os.environ.get("ABS_PASSWORD")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def abs_basics():
|
|
80
|
+
assert ABS_HOST is not None
|
|
81
|
+
assert ABS_USER is not None
|
|
82
|
+
assert ABS_PASSWORD is not None
|
|
83
|
+
|
|
84
|
+
logger = logging.getLogger()
|
|
85
|
+
logger.setLevel(logging.INFO)
|
|
86
|
+
|
|
87
|
+
async with aiohttp.ClientSession() as session:
|
|
88
|
+
client = await get_user_client(
|
|
89
|
+
session_config=SessionConfiguration(
|
|
90
|
+
session=session, url=ABS_HOST, logger=logger, pagination_items_per_page=30
|
|
91
|
+
),
|
|
92
|
+
username=ABS_USER,
|
|
93
|
+
password=ABS_PASSWORD,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# get libraries
|
|
97
|
+
libraries = await client.get_all_libraries()
|
|
98
|
+
|
|
99
|
+
# get library items
|
|
100
|
+
for library in libraries:
|
|
101
|
+
async for response in client.get_library_items(library_id=library.id_):
|
|
102
|
+
if not response.results:
|
|
103
|
+
break
|
|
104
|
+
for lib_item_minified in response.results:
|
|
105
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedPodcast):
|
|
106
|
+
...
|
|
107
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedBook):
|
|
108
|
+
...
|
|
109
|
+
|
|
110
|
+
# get a single podcast
|
|
111
|
+
podcast_id = "dda96167-eaad-4012-83e1-149c6700d3e8"
|
|
112
|
+
podcast_expanded = client.get_library_item_podcast(podcast_id=podcast_id, expanded=True)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
asyncio.run(abs_basics())
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Have a look into `aioaudiobookshelf/client/*.py` to see which endpoints are
|
|
119
|
+
currently implemented. And the [provider
|
|
120
|
+
implementation](https://github.com/music-assistant/server/blob/dev/music_assistant/providers/audiobookshelf/__init__.py) shows, how the lib can potentially be used.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# aioaudiobookshelf
|
|
2
|
+
Async python library to interact with
|
|
3
|
+
[Audiobookshelf](https://github.com/advplyr/audiobookshelf) (ABS).
|
|
4
|
+
|
|
5
|
+
This lib's primary goal is to be used within the Audiobookshelf music provider
|
|
6
|
+
in Music Assistant, but it can be used independently. Calls to endpoints not
|
|
7
|
+
needed for the provider will be added over time.
|
|
8
|
+
|
|
9
|
+
Not all endpoints are yet implemented.
|
|
10
|
+
|
|
11
|
+
## Releases
|
|
12
|
+
Releases can be found on [pypi](https://pypi.org/project/aioaudiobookshelf/),
|
|
13
|
+
and are tagged.
|
|
14
|
+
|
|
15
|
+
## Basic usage
|
|
16
|
+
ABS has a rest api, documented
|
|
17
|
+
[here](https://api.audiobookshelf.org) and additionally uses socket.io, see
|
|
18
|
+
[here](https://api.audiobookshelf.org/#socket) for some event driven
|
|
19
|
+
functionality.
|
|
20
|
+
Accessibility to the endpoints is determined by the [user
|
|
21
|
+
types](https://api.audiobookshelf.org/#user), which may be `root, admin, user, guest`.
|
|
22
|
+
This lib is not tested with a `guest` user.
|
|
23
|
+
|
|
24
|
+
As of `0.1.2` this lib has two different clients, the `UserClient` and the
|
|
25
|
+
`SocketClient`. Admin endpoints are not yet implemented. The user client
|
|
26
|
+
handles calls to the Rest API, the socket client allows to subscribe to certain
|
|
27
|
+
events.
|
|
28
|
+
|
|
29
|
+
To authenticate the socket client, you always need the user's token, username
|
|
30
|
+
and password are not enough. The user client can be authenticated by username
|
|
31
|
+
and password, which yields the token.
|
|
32
|
+
|
|
33
|
+
Usage example:
|
|
34
|
+
```python
|
|
35
|
+
import asyncio
|
|
36
|
+
import logging
|
|
37
|
+
import os
|
|
38
|
+
|
|
39
|
+
import aiohttp
|
|
40
|
+
|
|
41
|
+
from aioaudiobookshelf import SessionConfiguration, get_user_client
|
|
42
|
+
from aioaudiobookshelf.schema.library import LibraryItemMinifiedBook, LibraryItemMinifiedPodcast
|
|
43
|
+
|
|
44
|
+
ABS_HOST = os.environ.get("ABS_HOST")
|
|
45
|
+
ABS_USER = os.environ.get("ABS_USER")
|
|
46
|
+
ABS_PASSWORD = os.environ.get("ABS_PASSWORD")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def abs_basics():
|
|
50
|
+
assert ABS_HOST is not None
|
|
51
|
+
assert ABS_USER is not None
|
|
52
|
+
assert ABS_PASSWORD is not None
|
|
53
|
+
|
|
54
|
+
logger = logging.getLogger()
|
|
55
|
+
logger.setLevel(logging.INFO)
|
|
56
|
+
|
|
57
|
+
async with aiohttp.ClientSession() as session:
|
|
58
|
+
client = await get_user_client(
|
|
59
|
+
session_config=SessionConfiguration(
|
|
60
|
+
session=session, url=ABS_HOST, logger=logger, pagination_items_per_page=30
|
|
61
|
+
),
|
|
62
|
+
username=ABS_USER,
|
|
63
|
+
password=ABS_PASSWORD,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# get libraries
|
|
67
|
+
libraries = await client.get_all_libraries()
|
|
68
|
+
|
|
69
|
+
# get library items
|
|
70
|
+
for library in libraries:
|
|
71
|
+
async for response in client.get_library_items(library_id=library.id_):
|
|
72
|
+
if not response.results:
|
|
73
|
+
break
|
|
74
|
+
for lib_item_minified in response.results:
|
|
75
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedPodcast):
|
|
76
|
+
...
|
|
77
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedBook):
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
# get a single podcast
|
|
81
|
+
podcast_id = "dda96167-eaad-4012-83e1-149c6700d3e8"
|
|
82
|
+
podcast_expanded = client.get_library_item_podcast(podcast_id=podcast_id, expanded=True)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
asyncio.run(abs_basics())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Have a look into `aioaudiobookshelf/client/*.py` to see which endpoints are
|
|
89
|
+
currently implemented. And the [provider
|
|
90
|
+
implementation](https://github.com/music-assistant/server/blob/dev/music_assistant/providers/audiobookshelf/__init__.py) shows, how the lib can potentially be used.
|
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
from aiohttp.client_exceptions import ClientResponseError, InvalidUrlClientError
|
|
4
4
|
|
|
5
5
|
from aioaudiobookshelf.client import AdminClient, SessionConfiguration, SocketClient, UserClient
|
|
6
|
-
from aioaudiobookshelf.exceptions import LoginError
|
|
7
|
-
from aioaudiobookshelf.schema.calls_login import LoginParameters, LoginResponse
|
|
6
|
+
from aioaudiobookshelf.exceptions import LoginError, TokenIsMissingError
|
|
7
|
+
from aioaudiobookshelf.schema.calls_login import AuthorizeResponse, LoginParameters, LoginResponse
|
|
8
8
|
|
|
9
|
-
__version__ = "0.1.
|
|
9
|
+
__version__ = "0.1.3"
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
async def _get_login_response(
|
|
13
13
|
*, session_config: SessionConfiguration, username: str, password: str
|
|
14
14
|
) -> LoginResponse:
|
|
15
|
+
"""Login via username and password."""
|
|
15
16
|
login_request = LoginParameters(username=username, password=password).to_dict()
|
|
16
17
|
|
|
17
18
|
try:
|
|
@@ -26,6 +27,42 @@ async def _get_login_response(
|
|
|
26
27
|
return LoginResponse.from_json(await resp.read())
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
async def _get_authorize_response(*, session_config: SessionConfiguration) -> AuthorizeResponse:
|
|
31
|
+
"""Login via token."""
|
|
32
|
+
try:
|
|
33
|
+
resp = await session_config.session.post(
|
|
34
|
+
f"{session_config.url}/api/authorize",
|
|
35
|
+
ssl=session_config.verify_ssl,
|
|
36
|
+
raise_for_status=True,
|
|
37
|
+
headers=session_config.headers,
|
|
38
|
+
)
|
|
39
|
+
except (ClientResponseError, InvalidUrlClientError, TokenIsMissingError) as exc:
|
|
40
|
+
raise LoginError from exc
|
|
41
|
+
return AuthorizeResponse.from_json(await resp.read())
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def get_user_client_by_token(*, session_config: SessionConfiguration) -> UserClient:
|
|
45
|
+
"""Get user client by token. Token must be set in session_config."""
|
|
46
|
+
authorize_response = await _get_authorize_response(session_config=session_config)
|
|
47
|
+
return UserClient(session_config=session_config, login_response=authorize_response)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def get_user_and_socket_client_by_token(
|
|
51
|
+
*, session_config: SessionConfiguration
|
|
52
|
+
) -> tuple[UserClient, SocketClient]:
|
|
53
|
+
"""Get user and socket client by token. Token must be set in session_config."""
|
|
54
|
+
authorize_response = await _get_authorize_response(session_config=session_config)
|
|
55
|
+
user_client = UserClient(session_config=session_config, login_response=authorize_response)
|
|
56
|
+
socket_client = SocketClient(session_config=session_config)
|
|
57
|
+
return user_client, socket_client
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
async def get_admin_client_by_token(*, session_config: SessionConfiguration) -> AdminClient:
|
|
61
|
+
"""Get admin client by token. Token must be set in session_config."""
|
|
62
|
+
authorize_response = await _get_authorize_response(session_config=session_config)
|
|
63
|
+
return AdminClient(session_config=session_config, login_response=authorize_response)
|
|
64
|
+
|
|
65
|
+
|
|
29
66
|
async def get_user_client(
|
|
30
67
|
*,
|
|
31
68
|
session_config: SessionConfiguration,
|
|
@@ -9,7 +9,7 @@ import socketio
|
|
|
9
9
|
import socketio.exceptions
|
|
10
10
|
from aiohttp import ClientSession
|
|
11
11
|
|
|
12
|
-
from aioaudiobookshelf.exceptions import BadUserError
|
|
12
|
+
from aioaudiobookshelf.exceptions import BadUserError, TokenIsMissingError
|
|
13
13
|
from aioaudiobookshelf.schema.events_socket import (
|
|
14
14
|
LibraryItemRemoved,
|
|
15
15
|
PodcastEpisodeDownload,
|
|
@@ -37,7 +37,7 @@ class SessionConfiguration:
|
|
|
37
37
|
session: ClientSession
|
|
38
38
|
url: str
|
|
39
39
|
verify_ssl: bool = True
|
|
40
|
-
token: str =
|
|
40
|
+
token: str | None = None
|
|
41
41
|
pagination_items_per_page: int = 10
|
|
42
42
|
logger: logging.Logger | None = None
|
|
43
43
|
|
|
@@ -45,7 +45,7 @@ class SessionConfiguration:
|
|
|
45
45
|
def headers(self) -> dict[str, str]:
|
|
46
46
|
"""Session headers."""
|
|
47
47
|
if self.token is None:
|
|
48
|
-
raise
|
|
48
|
+
raise TokenIsMissingError("Token not set.")
|
|
49
49
|
return {"Authorization": f"Bearer {self.token}"}
|
|
50
50
|
|
|
51
51
|
def __post_init__(self) -> None:
|
|
@@ -26,3 +26,7 @@ class LoginResponse(DataClassJSONMixin):
|
|
|
26
26
|
user_default_library_id: Annotated[str, Alias("userDefaultLibraryId")]
|
|
27
27
|
server_settings: Annotated[ServerSettings, Alias("serverSettings")]
|
|
28
28
|
source: Annotated[str, Alias("Source")]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# api/authorize, if token is used for authorization
|
|
32
|
+
AuthorizeResponse = LoginResponse
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: aioaudiobookshelf
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Async library for Audiobookshelf
|
|
5
|
+
Author-email: Fabian Munkes <105975993+fmunkes@users.noreply.github.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Platform: any
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: aiohttp
|
|
15
|
+
Requires-Dist: mashumaro
|
|
16
|
+
Requires-Dist: python-socketio>=5.12
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: codespell==2.3.0; extra == "test"
|
|
19
|
+
Requires-Dist: isort==5.13.2; extra == "test"
|
|
20
|
+
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
21
|
+
Requires-Dist: pre-commit==4.0.1; extra == "test"
|
|
22
|
+
Requires-Dist: pre-commit-hooks==5.0.0; extra == "test"
|
|
23
|
+
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
24
|
+
Requires-Dist: pytest-aiohttp==1.0.5; extra == "test"
|
|
25
|
+
Requires-Dist: pytest-cov==5.0.0; extra == "test"
|
|
26
|
+
Requires-Dist: syrupy==4.8.1; extra == "test"
|
|
27
|
+
Requires-Dist: tomli==2.2.1; extra == "test"
|
|
28
|
+
Requires-Dist: ruff==0.9.2; extra == "test"
|
|
29
|
+
Requires-Dist: bumpver; extra == "test"
|
|
30
|
+
|
|
31
|
+
# aioaudiobookshelf
|
|
32
|
+
Async python library to interact with
|
|
33
|
+
[Audiobookshelf](https://github.com/advplyr/audiobookshelf) (ABS).
|
|
34
|
+
|
|
35
|
+
This lib's primary goal is to be used within the Audiobookshelf music provider
|
|
36
|
+
in Music Assistant, but it can be used independently. Calls to endpoints not
|
|
37
|
+
needed for the provider will be added over time.
|
|
38
|
+
|
|
39
|
+
Not all endpoints are yet implemented.
|
|
40
|
+
|
|
41
|
+
## Releases
|
|
42
|
+
Releases can be found on [pypi](https://pypi.org/project/aioaudiobookshelf/),
|
|
43
|
+
and are tagged.
|
|
44
|
+
|
|
45
|
+
## Basic usage
|
|
46
|
+
ABS has a rest api, documented
|
|
47
|
+
[here](https://api.audiobookshelf.org) and additionally uses socket.io, see
|
|
48
|
+
[here](https://api.audiobookshelf.org/#socket) for some event driven
|
|
49
|
+
functionality.
|
|
50
|
+
Accessibility to the endpoints is determined by the [user
|
|
51
|
+
types](https://api.audiobookshelf.org/#user), which may be `root, admin, user, guest`.
|
|
52
|
+
This lib is not tested with a `guest` user.
|
|
53
|
+
|
|
54
|
+
As of `0.1.2` this lib has two different clients, the `UserClient` and the
|
|
55
|
+
`SocketClient`. Admin endpoints are not yet implemented. The user client
|
|
56
|
+
handles calls to the Rest API, the socket client allows to subscribe to certain
|
|
57
|
+
events.
|
|
58
|
+
|
|
59
|
+
To authenticate the socket client, you always need the user's token, username
|
|
60
|
+
and password are not enough. The user client can be authenticated by username
|
|
61
|
+
and password, which yields the token.
|
|
62
|
+
|
|
63
|
+
Usage example:
|
|
64
|
+
```python
|
|
65
|
+
import asyncio
|
|
66
|
+
import logging
|
|
67
|
+
import os
|
|
68
|
+
|
|
69
|
+
import aiohttp
|
|
70
|
+
|
|
71
|
+
from aioaudiobookshelf import SessionConfiguration, get_user_client
|
|
72
|
+
from aioaudiobookshelf.schema.library import LibraryItemMinifiedBook, LibraryItemMinifiedPodcast
|
|
73
|
+
|
|
74
|
+
ABS_HOST = os.environ.get("ABS_HOST")
|
|
75
|
+
ABS_USER = os.environ.get("ABS_USER")
|
|
76
|
+
ABS_PASSWORD = os.environ.get("ABS_PASSWORD")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def abs_basics():
|
|
80
|
+
assert ABS_HOST is not None
|
|
81
|
+
assert ABS_USER is not None
|
|
82
|
+
assert ABS_PASSWORD is not None
|
|
83
|
+
|
|
84
|
+
logger = logging.getLogger()
|
|
85
|
+
logger.setLevel(logging.INFO)
|
|
86
|
+
|
|
87
|
+
async with aiohttp.ClientSession() as session:
|
|
88
|
+
client = await get_user_client(
|
|
89
|
+
session_config=SessionConfiguration(
|
|
90
|
+
session=session, url=ABS_HOST, logger=logger, pagination_items_per_page=30
|
|
91
|
+
),
|
|
92
|
+
username=ABS_USER,
|
|
93
|
+
password=ABS_PASSWORD,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# get libraries
|
|
97
|
+
libraries = await client.get_all_libraries()
|
|
98
|
+
|
|
99
|
+
# get library items
|
|
100
|
+
for library in libraries:
|
|
101
|
+
async for response in client.get_library_items(library_id=library.id_):
|
|
102
|
+
if not response.results:
|
|
103
|
+
break
|
|
104
|
+
for lib_item_minified in response.results:
|
|
105
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedPodcast):
|
|
106
|
+
...
|
|
107
|
+
if isinstance(lib_item_minified, LibraryItemMinifiedBook):
|
|
108
|
+
...
|
|
109
|
+
|
|
110
|
+
# get a single podcast
|
|
111
|
+
podcast_id = "dda96167-eaad-4012-83e1-149c6700d3e8"
|
|
112
|
+
podcast_expanded = client.get_library_item_podcast(podcast_id=podcast_id, expanded=True)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
asyncio.run(abs_basics())
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Have a look into `aioaudiobookshelf/client/*.py` to see which endpoints are
|
|
119
|
+
currently implemented. And the [provider
|
|
120
|
+
implementation](https://github.com/music-assistant/server/blob/dev/music_assistant/providers/audiobookshelf/__init__.py) shows, how the lib can potentially be used.
|
|
@@ -18,7 +18,7 @@ description = "Async library for Audiobookshelf"
|
|
|
18
18
|
license = {text = "Apache-2.0"}
|
|
19
19
|
readme = "README.md"
|
|
20
20
|
requires-python = ">=3.12"
|
|
21
|
-
version = "0.1.
|
|
21
|
+
version = "0.1.3"
|
|
22
22
|
|
|
23
23
|
[project.optional-dependencies]
|
|
24
24
|
test = [
|
|
@@ -133,13 +133,13 @@ known-first-party = ["music_assistant"]
|
|
|
133
133
|
max-complexity = 25
|
|
134
134
|
|
|
135
135
|
[tool.bumpver]
|
|
136
|
-
current_version = "0.1.
|
|
136
|
+
current_version = "0.1.3"
|
|
137
137
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
138
138
|
commit_message = "bump version {old_version} -> {new_version}"
|
|
139
139
|
tag_message = "{new_version}"
|
|
140
140
|
commit = true
|
|
141
141
|
tag = true
|
|
142
|
-
push =
|
|
142
|
+
push = true
|
|
143
143
|
|
|
144
144
|
[tool.bumpver.file_patterns]
|
|
145
145
|
"pyproject.toml" = [
|
aioaudiobookshelf-0.1.2/PKG-INFO
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: aioaudiobookshelf
|
|
3
|
-
Version: 0.1.2
|
|
4
|
-
Summary: Async library for Audiobookshelf
|
|
5
|
-
Author-email: Fabian Munkes <105975993+fmunkes@users.noreply.github.com>
|
|
6
|
-
License: Apache-2.0
|
|
7
|
-
Platform: any
|
|
8
|
-
Classifier: Environment :: Console
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
-
Requires-Python: >=3.12
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: aiohttp
|
|
15
|
-
Requires-Dist: mashumaro
|
|
16
|
-
Requires-Dist: python-socketio>=5.12
|
|
17
|
-
Provides-Extra: test
|
|
18
|
-
Requires-Dist: codespell==2.3.0; extra == "test"
|
|
19
|
-
Requires-Dist: isort==5.13.2; extra == "test"
|
|
20
|
-
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
21
|
-
Requires-Dist: pre-commit==4.0.1; extra == "test"
|
|
22
|
-
Requires-Dist: pre-commit-hooks==5.0.0; extra == "test"
|
|
23
|
-
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
24
|
-
Requires-Dist: pytest-aiohttp==1.0.5; extra == "test"
|
|
25
|
-
Requires-Dist: pytest-cov==5.0.0; extra == "test"
|
|
26
|
-
Requires-Dist: syrupy==4.8.1; extra == "test"
|
|
27
|
-
Requires-Dist: tomli==2.2.1; extra == "test"
|
|
28
|
-
Requires-Dist: ruff==0.9.2; extra == "test"
|
|
29
|
-
Requires-Dist: bumpver; extra == "test"
|
|
30
|
-
|
|
31
|
-
# aioaudiobookshelf
|
|
32
|
-
Async python library to interact with Audiobookshelf
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: aioaudiobookshelf
|
|
3
|
-
Version: 0.1.2
|
|
4
|
-
Summary: Async library for Audiobookshelf
|
|
5
|
-
Author-email: Fabian Munkes <105975993+fmunkes@users.noreply.github.com>
|
|
6
|
-
License: Apache-2.0
|
|
7
|
-
Platform: any
|
|
8
|
-
Classifier: Environment :: Console
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
-
Requires-Python: >=3.12
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: aiohttp
|
|
15
|
-
Requires-Dist: mashumaro
|
|
16
|
-
Requires-Dist: python-socketio>=5.12
|
|
17
|
-
Provides-Extra: test
|
|
18
|
-
Requires-Dist: codespell==2.3.0; extra == "test"
|
|
19
|
-
Requires-Dist: isort==5.13.2; extra == "test"
|
|
20
|
-
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
21
|
-
Requires-Dist: pre-commit==4.0.1; extra == "test"
|
|
22
|
-
Requires-Dist: pre-commit-hooks==5.0.0; extra == "test"
|
|
23
|
-
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
24
|
-
Requires-Dist: pytest-aiohttp==1.0.5; extra == "test"
|
|
25
|
-
Requires-Dist: pytest-cov==5.0.0; extra == "test"
|
|
26
|
-
Requires-Dist: syrupy==4.8.1; extra == "test"
|
|
27
|
-
Requires-Dist: tomli==2.2.1; extra == "test"
|
|
28
|
-
Requires-Dist: ruff==0.9.2; extra == "test"
|
|
29
|
-
Requires-Dist: bumpver; extra == "test"
|
|
30
|
-
|
|
31
|
-
# aioaudiobookshelf
|
|
32
|
-
Async python library to interact with Audiobookshelf
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/collections_.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_authors.py
RENAMED
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_collections.py
RENAMED
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_library.py
RENAMED
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_playlists.py
RENAMED
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_series.py
RENAMED
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_session.py
RENAMED
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/events_socket.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/media_progress.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/series_books.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|