kabooz 0.1.0__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.
- kabooz-0.1.0/.github/workflows/publish.yml +75 -0
- kabooz-0.1.0/.gitignore +3 -0
- kabooz-0.1.0/CREDITS.md +150 -0
- kabooz-0.1.0/DEVLOG.md +40 -0
- kabooz-0.1.0/LICENSE +661 -0
- kabooz-0.1.0/PKG-INFO +372 -0
- kabooz-0.1.0/README.md +336 -0
- kabooz-0.1.0/docs/architecture.md +197 -0
- kabooz-0.1.0/docs/authentication.md +112 -0
- kabooz-0.1.0/docs/cli.md +460 -0
- kabooz-0.1.0/docs/configuration.md +160 -0
- kabooz-0.1.0/docs/contributing.md +123 -0
- kabooz-0.1.0/docs/installation.md +43 -0
- kabooz-0.1.0/docs/library.md +405 -0
- kabooz-0.1.0/docs/naming.md +162 -0
- kabooz-0.1.0/kabooz/__init__.py +32 -0
- kabooz-0.1.0/kabooz/auth/__init__.py +3 -0
- kabooz-0.1.0/kabooz/auth/credentials.py +234 -0
- kabooz-0.1.0/kabooz/auth/session.py +111 -0
- kabooz-0.1.0/kabooz/cli.py +2036 -0
- kabooz-0.1.0/kabooz/client.py +1338 -0
- kabooz-0.1.0/kabooz/config.py +280 -0
- kabooz-0.1.0/kabooz/data/__init__.py +0 -0
- kabooz-0.1.0/kabooz/data/dev_audio.opus +0 -0
- kabooz-0.1.0/kabooz/dev.py +310 -0
- kabooz-0.1.0/kabooz/download/__init__.py +12 -0
- kabooz-0.1.0/kabooz/download/credits.py +174 -0
- kabooz-0.1.0/kabooz/download/downloader.py +604 -0
- kabooz-0.1.0/kabooz/download/lyrics.py +156 -0
- kabooz-0.1.0/kabooz/download/musicbrainz.py +152 -0
- kabooz-0.1.0/kabooz/download/naming.py +289 -0
- kabooz-0.1.0/kabooz/download/tagger.py +493 -0
- kabooz-0.1.0/kabooz/exceptions.py +103 -0
- kabooz-0.1.0/kabooz/local/__init__.py +38 -0
- kabooz-0.1.0/kabooz/local/export.py +582 -0
- kabooz-0.1.0/kabooz/local/playlist.py +211 -0
- kabooz-0.1.0/kabooz/local/store.py +421 -0
- kabooz-0.1.0/kabooz/models/__init__.py +24 -0
- kabooz-0.1.0/kabooz/models/album.py +195 -0
- kabooz-0.1.0/kabooz/models/artist.py +80 -0
- kabooz-0.1.0/kabooz/models/common.py +183 -0
- kabooz-0.1.0/kabooz/models/favorites.py +123 -0
- kabooz-0.1.0/kabooz/models/playlist.py +164 -0
- kabooz-0.1.0/kabooz/models/release.py +223 -0
- kabooz-0.1.0/kabooz/models/search.py +202 -0
- kabooz-0.1.0/kabooz/models/track.py +179 -0
- kabooz-0.1.0/kabooz/models/user.py +143 -0
- kabooz-0.1.0/kabooz/quality.py +48 -0
- kabooz-0.1.0/kabooz/session.py +1734 -0
- kabooz-0.1.0/kabooz/tui.py +1178 -0
- kabooz-0.1.0/kabooz/tui_curses.py +1067 -0
- kabooz-0.1.0/kabooz/url.py +93 -0
- kabooz-0.1.0/pyproject.toml +62 -0
- kabooz-0.1.0/scratch.py +453 -0
- kabooz-0.1.0/scripts/make_dev_audio.py +82 -0
- kabooz-0.1.0/tests/test_catalog.py +358 -0
- kabooz-0.1.0/tests/test_client.py +221 -0
- kabooz-0.1.0/tests/test_downloader.py +280 -0
- kabooz-0.1.0/tests/test_imports.py +429 -0
- kabooz-0.1.0/tests/test_local.py +425 -0
- kabooz-0.1.0/tests/test_models.py +390 -0
- kabooz-0.1.0/tests/test_new_models.py +366 -0
- kabooz-0.1.0/tests/test_session_persistence.py +108 -0
- kabooz-0.1.0/tests/test_tagger.py +338 -0
- kabooz-0.1.0/tests/test_url.py +61 -0
- kabooz-0.1.0/tools/devlog.py +721 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*" # triggers on v0.1.0, v1.2.3, etc.
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distribution
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
|
|
21
|
+
- name: Install build tools
|
|
22
|
+
run: pip install build
|
|
23
|
+
|
|
24
|
+
- name: Build wheel and sdist
|
|
25
|
+
run: python -m build
|
|
26
|
+
|
|
27
|
+
- name: Store distribution artifacts
|
|
28
|
+
uses: actions/upload-artifact@v4
|
|
29
|
+
with:
|
|
30
|
+
name: dist
|
|
31
|
+
path: dist/
|
|
32
|
+
|
|
33
|
+
publish-pypi:
|
|
34
|
+
name: Publish to PyPI
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- name: Download distribution artifacts
|
|
40
|
+
uses: actions/download-artifact@v4
|
|
41
|
+
with:
|
|
42
|
+
name: dist
|
|
43
|
+
path: dist/
|
|
44
|
+
|
|
45
|
+
- name: Publish to PyPI
|
|
46
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
47
|
+
with:
|
|
48
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
49
|
+
|
|
50
|
+
github-release:
|
|
51
|
+
name: Create GitHub release
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
|
|
55
|
+
permissions:
|
|
56
|
+
contents: write
|
|
57
|
+
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
|
|
61
|
+
- name: Download distribution artifacts
|
|
62
|
+
uses: actions/download-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/
|
|
66
|
+
|
|
67
|
+
- name: Create GitHub release
|
|
68
|
+
env:
|
|
69
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
70
|
+
run: |
|
|
71
|
+
gh release create "${{ github.ref_name }}" \
|
|
72
|
+
--title "Kabooz ${{ github.ref_name }}" \
|
|
73
|
+
--generate-notes \
|
|
74
|
+
dist/*
|
|
75
|
+
|
kabooz-0.1.0/.gitignore
ADDED
kabooz-0.1.0/CREDITS.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Credits
|
|
2
|
+
|
|
3
|
+
Kabooz exists because of the people and services below. This file is an attempt
|
|
4
|
+
to give proper credit rather than just a bullet list.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Qobuz
|
|
9
|
+
|
|
10
|
+
*https://www.qobuz.com*
|
|
11
|
+
|
|
12
|
+
Kabooz would be a meaningless piece of software without Qobuz. It is worth saying
|
|
13
|
+
that plainly, even in a tool that talks to Qobuz's API without official sanction.
|
|
14
|
+
|
|
15
|
+
Qobuz is one of the few streaming services that has genuinely cared about music as
|
|
16
|
+
an art form rather than as content. In an industry that spent years training people
|
|
17
|
+
to think music was worth nothing — a monthly fee for infinite disposable background
|
|
18
|
+
noise — Qobuz held a different position. It insisted that the recording quality
|
|
19
|
+
mattered, that the people who made the music deserved to be paid properly, and that
|
|
20
|
+
the listeners who wanted more than a compressed MP3 deserved to get it.
|
|
21
|
+
|
|
22
|
+
The catalog is serious. Not just the obvious canonical recordings, but deep cuts,
|
|
23
|
+
obscure chamber music, early music on period instruments, jazz from labels most
|
|
24
|
+
people have never heard of, folk traditions from places most streaming algorithms
|
|
25
|
+
would never surface. The kind of catalog that a person who actually listens to music
|
|
26
|
+
built, not one assembled by a recommendation engine optimizing for passive listening
|
|
27
|
+
time.
|
|
28
|
+
|
|
29
|
+
The hi-res audio is real. Not upsampled. The bit depths and sampling rates on offer
|
|
30
|
+
correspond to actual source material, which matters in ways that are hard to explain
|
|
31
|
+
to someone who hasn't heard the difference but immediately obvious to someone who has.
|
|
32
|
+
A 24-bit 96 kHz transfer of an analogue master sounds different from a 16-bit 44.1 kHz
|
|
33
|
+
version of the same recording. Sometimes profoundly so. Qobuz provides that access.
|
|
34
|
+
|
|
35
|
+
The business model is honest. You pay a subscription. Qobuz pays the labels and
|
|
36
|
+
through them, artists. There are no advertisements. The service does not harvest and
|
|
37
|
+
sell your listening data as its primary product. The money flows from the person who
|
|
38
|
+
wants to listen to music toward the people who made it, which is how it should work.
|
|
39
|
+
|
|
40
|
+
The Qobuz editorial team is worth mentioning separately. The reviews and listening
|
|
41
|
+
guides on the platform are written by people who know music — not auto-generated
|
|
42
|
+
summaries, not marketing copy, but actual critical writing about recordings and
|
|
43
|
+
composers and performers and why a particular release is worth your time. That is
|
|
44
|
+
increasingly rare and it deserves to be noticed.
|
|
45
|
+
|
|
46
|
+
None of this means Kabooz is endorsed by or affiliated with Qobuz. It is not. Kabooz
|
|
47
|
+
is an unofficial tool built by someone who uses Qobuz and wanted a way to work with
|
|
48
|
+
it from the command line. In the meantime, if you use Kabooz and you do not already
|
|
49
|
+
have a Qobuz subscription, please consider getting one. The service deserves the revenue.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## MusicBrainz
|
|
54
|
+
|
|
55
|
+
*https://musicbrainz.org*
|
|
56
|
+
|
|
57
|
+
MusicBrainz is the open music encyclopedia. It is a community-maintained database of
|
|
58
|
+
recordings, releases, artists, labels, works, and the relationships between all of them
|
|
59
|
+
— maintained not by a corporation but by volunteers who care about music metadata being
|
|
60
|
+
correct and complete.
|
|
61
|
+
|
|
62
|
+
Kabooz uses MusicBrainz to enrich audio tags beyond what the Qobuz API provides. When
|
|
63
|
+
you have an ISRC code for a track, MusicBrainz can tell you the official MusicBrainz
|
|
64
|
+
recording ID, the release group it belongs to, whether it is a live recording or a
|
|
65
|
+
studio take, which label released it in which country, and a great deal more. That
|
|
66
|
+
information ends up embedded in your audio files, where it can be used by any player
|
|
67
|
+
or library manager that knows how to read it.
|
|
68
|
+
|
|
69
|
+
The MusicBrainz project is not glamorous work. Correcting metadata, merging duplicate
|
|
70
|
+
entries, adding missing releases, standardizing artist names across scripts and
|
|
71
|
+
transliterations — it is painstaking and unglamorous and the people who do it are
|
|
72
|
+
rarely thanked. They should be.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## LRCLIB
|
|
77
|
+
|
|
78
|
+
*https://lrclib.net*
|
|
79
|
+
|
|
80
|
+
LRCLIB is a free, open, no-authentication-required database of synced lyrics in LRC
|
|
81
|
+
format. LRC is the format where each line of lyrics is tagged with a timestamp — the
|
|
82
|
+
format that makes lyrics scroll in sync with the music in players that support it.
|
|
83
|
+
|
|
84
|
+
Kabooz uses LRCLIB to fetch synced lyrics and embed them in downloaded audio files,
|
|
85
|
+
both as synced LRC data for players that can display it in time and as plain text for
|
|
86
|
+
players that cannot. The result is that your local files have lyrics without requiring
|
|
87
|
+
any additional software or service.
|
|
88
|
+
|
|
89
|
+
LRCLIB asks nothing in return. No account, no API key, no rate limit that requires
|
|
90
|
+
you to prove you are a legitimate user. It simply has a database of lyrics and an
|
|
91
|
+
HTTP endpoint that returns them. That straightforward, non-extractive approach to
|
|
92
|
+
providing a useful service is worth appreciating explicitly.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## tmxkwpn
|
|
97
|
+
|
|
98
|
+
*@tmxkwpn on Telegram*
|
|
99
|
+
|
|
100
|
+
Technical help and guidance during development. Kabooz would have taken longer and
|
|
101
|
+
worked worse without it.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Python dependencies
|
|
106
|
+
|
|
107
|
+
These libraries do the actual work underneath Kabooz's surface.
|
|
108
|
+
|
|
109
|
+
**httpx** *(github.com/encode/httpx)* — the HTTP client that handles all communication
|
|
110
|
+
with the Qobuz API and the CDN. Reliable, well-documented, and a genuine improvement
|
|
111
|
+
over the alternatives.
|
|
112
|
+
|
|
113
|
+
**mutagen** *(github.com/quodlibet/mutagen)* — reads and writes audio metadata for
|
|
114
|
+
FLAC and MP3 files. The Quod Libet project has maintained this library for a long time
|
|
115
|
+
and it handles edge cases that simpler libraries miss.
|
|
116
|
+
|
|
117
|
+
**Typer** *(github.com/tiangolo/typer)* — the CLI framework that turns Python function
|
|
118
|
+
signatures into command-line interfaces. It makes the CLI code read like what it does
|
|
119
|
+
rather than like argument parsing boilerplate.
|
|
120
|
+
|
|
121
|
+
**Rich** *(github.com/Textualize/rich)* — terminal formatting. The progress bars,
|
|
122
|
+
colored output, tables, and panels that make Kabooz's output readable rather than a
|
|
123
|
+
wall of plain text.
|
|
124
|
+
|
|
125
|
+
**tomli-w** *(github.com/hukkin/tomli-w)* — writes TOML configuration files. Small,
|
|
126
|
+
does one thing, does it correctly.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## A note on the name
|
|
131
|
+
|
|
132
|
+
Kabooz is phonetically close to Qobuz. That is intentional. The connection should be
|
|
133
|
+
legible to anyone who sees it. The distance from the real name is also intentional —
|
|
134
|
+
it is not Qobuz, it is not affiliated with Qobuz, and the name reflects both of those
|
|
135
|
+
things at once.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
Kabooz is released under the AGPL-3.0-or-later license. The full text is in the
|
|
142
|
+
LICENSE file. The short version: you can use it, study it, modify it, and distribute
|
|
143
|
+
it, but if you distribute a modified version you must make the source available under
|
|
144
|
+
the same terms.
|
|
145
|
+
|
|
146
|
+
This is not a legal barrier to tinkering. Modify the code. Add features. Fix bugs.
|
|
147
|
+
Make it work better for your use case. The AGPL is designed to keep improvements in
|
|
148
|
+
the commons rather than allowing them to disappear into proprietary forks, which
|
|
149
|
+
seems like the right disposition for a tool like this.
|
|
150
|
+
|
kabooz-0.1.0/DEVLOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
\
|
|
2
|
+
# DEV LOGS
|
|
3
|
+
|
|
4
|
+
This file records logs written by the developer for future reference (self or collaborators).
|
|
5
|
+
This is NOT user documentation; it exists purely for developer reference.
|
|
6
|
+
Entries may be incomplete, outdated, or inaccurate.
|
|
7
|
+
|
|
8
|
+
## Format
|
|
9
|
+
1. An entry should be made every session.
|
|
10
|
+
A session usually corresponds to a single day.
|
|
11
|
+
2. All dates must be in UTC. Mentioning time is discouraged; if used, it must also be in UTC.
|
|
12
|
+
3. This file should be updated in the last commit of a session, and should be omitted in **Commits Made** list.
|
|
13
|
+
4. A single session entry must follow this format:
|
|
14
|
+
|
|
15
|
+
### YYYY-MM-DD
|
|
16
|
+
**Author**: [Your name / alias]
|
|
17
|
+
**Commits Made**: commit list or range
|
|
18
|
+
|
|
19
|
+
- Use bullet points.
|
|
20
|
+
- Use explicit sub-headings (####) such as:
|
|
21
|
+
- TODO
|
|
22
|
+
- DONE
|
|
23
|
+
- NOTES
|
|
24
|
+
- BUGS
|
|
25
|
+
- IDEAS
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### 2026-03-17
|
|
31
|
+
**Author**: [TchaikovskyCannonsAPI]
|
|
32
|
+
**Commits Made**: 6a88b36..c477381
|
|
33
|
+
#### DONE
|
|
34
|
+
- [x] Lets leave it, cuz it would be soo long
|
|
35
|
+
- [x] Fixed dev.py to be better in dev audio integrity. We don't wanna loose the rick roll in any case.
|
|
36
|
+
- [x] Made cover.jpg for singles copy the track file name instead of cover.jog
|
|
37
|
+
#### BUGS
|
|
38
|
+
- When downloading MP3, the template adds this in the folder name `Billie Jean [FLAC 16bit 44.1kHz] [2026]`
|
|
39
|
+
- When running TUI curses, and clicking on Mozart's Don Giovanni album by Carlo ... remastered 2016, it returns the error ` Overture [24bit/96kHz] Philharmonia Orchestra — Mozart : Don Giovanni (2016 Remastered) █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0:18 / 6:18 ⏸ PAUSED space=pause n=next p=prev r=radio [/]=vol 100% ←/→=±10s q=quit Loading: Mozart : Don Giovanni (2016 Remastered)… [DEV] GET /album/get params=['album_id', 'limit', 'offset'] → fetching… [DEV] GET /album/get params=['album_id', 'limit', 'offset'] → fetching… [DEV] GET /album/get → HTTP 200 (cached) ✗ Load error: 'TrackSummary' object has no attribute 'performer' [DEV] GET /album/get → HTTP 200 (cached)`
|
|
40
|
+
|