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.

Files changed (54) hide show
  1. aioaudiobookshelf-0.1.3/PKG-INFO +120 -0
  2. aioaudiobookshelf-0.1.3/README.md +90 -0
  3. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/__init__.py +40 -3
  4. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/__init__.py +3 -3
  5. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/exceptions.py +4 -0
  6. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_login.py +4 -0
  7. aioaudiobookshelf-0.1.3/aioaudiobookshelf.egg-info/PKG-INFO +120 -0
  8. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/pyproject.toml +3 -3
  9. aioaudiobookshelf-0.1.2/PKG-INFO +0 -32
  10. aioaudiobookshelf-0.1.2/README.md +0 -2
  11. aioaudiobookshelf-0.1.2/aioaudiobookshelf.egg-info/PKG-INFO +0 -32
  12. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/LICENSE +0 -0
  13. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/_base.py +0 -0
  14. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/authors.py +0 -0
  15. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/collections_.py +0 -0
  16. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/items.py +0 -0
  17. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/libraries.py +0 -0
  18. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/me.py +0 -0
  19. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/playlists.py +0 -0
  20. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/podcasts.py +0 -0
  21. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/series.py +0 -0
  22. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/client/session.py +0 -0
  23. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/helpers.py +0 -0
  24. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/__init__.py +0 -0
  25. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/audio.py +0 -0
  26. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/author.py +0 -0
  27. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/book.py +0 -0
  28. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_authors.py +0 -0
  29. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_collections.py +0 -0
  30. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_items.py +0 -0
  31. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_library.py +0 -0
  32. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_me.py +0 -0
  33. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_playlists.py +0 -0
  34. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_series.py +0 -0
  35. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/calls_session.py +0 -0
  36. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/collection.py +0 -0
  37. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/events_socket.py +0 -0
  38. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/file.py +0 -0
  39. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/folder.py +0 -0
  40. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/library.py +0 -0
  41. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/media_progress.py +0 -0
  42. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/playlist.py +0 -0
  43. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/podcast.py +0 -0
  44. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/series.py +0 -0
  45. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/series_books.py +0 -0
  46. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/server.py +0 -0
  47. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/session.py +0 -0
  48. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf/schema/user.py +0 -0
  49. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/SOURCES.txt +0 -0
  50. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/dependency_links.txt +0 -0
  51. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/not-zip-safe +0 -0
  52. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/requires.txt +0 -0
  53. {aioaudiobookshelf-0.1.2 → aioaudiobookshelf-0.1.3}/aioaudiobookshelf.egg-info/top_level.txt +0 -0
  54. {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.2"
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 RuntimeError("Token not set.")
48
+ raise TokenIsMissingError("Token not set.")
49
49
  return {"Authorization": f"Bearer {self.token}"}
50
50
 
51
51
  def __post_init__(self) -> None:
@@ -11,3 +11,7 @@ class LoginError(Exception):
11
11
 
12
12
  class ApiError(Exception):
13
13
  """Exception raised if call to api failed."""
14
+
15
+
16
+ class TokenIsMissingError(Exception):
17
+ """Exception raised if token is missing."""
@@ -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.2"
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.2"
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 = false
142
+ push = true
143
143
 
144
144
  [tool.bumpver.file_patterns]
145
145
  "pyproject.toml" = [
@@ -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,2 +0,0 @@
1
- # aioaudiobookshelf
2
- 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