Compare commits

...

2 Commits

Author SHA1 Message Date
2d038fc811 feat: add base class and authentication for now 2025-12-05 17:05:54 +01:00
fbd987d353 docs: add stats.py 2025-12-05 17:05:44 +01:00
2 changed files with 63 additions and 2 deletions

View File

@@ -16,8 +16,9 @@ Look at the [roadmap](#roadmap) for more details.
It's still a work in progress, so : It's still a work in progress, so :
- all the code is in `main.py` with exceptions: - currently, most code resides in `main.py`, except for some experimental files that aren't part of the final structure:
- `player.py` is the test playground for the download and play functionality - `player.py` is the test playground for the download and play functionality
- `stats.py` is the test playground for the stats functionality
- expect bugs and missing features - expect bugs and missing features
- the code is not yet organized as I'm currently experimenting - the code is not yet organized as I'm currently experimenting
@@ -30,7 +31,7 @@ This project uses [uv](https://github.com/astral-sh/uv) for dependency managemen
$ uv sync $ uv sync
# run the TUI # run the TUI
$ uv run main.py $ uv run main.py # or player.py or stats.py
``` ```
Please also note that as of now, you need to have [ffmpeg](https://ffmpeg.org/) installed to play audio files. Please also note that as of now, you need to have [ffmpeg](https://ffmpeg.org/) installed to play audio files.

60
stats.py Normal file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Stats playground for Audible TUI - get your listening stats"""
import logging
from getpass import getpass
from pathlib import Path
import audible
logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)
logging.getLogger("audible").setLevel(logging.WARNING)
class AudibleStats:
"""Class to handle Audible authentication and stats retrieval."""
def __init__(self) -> None:
"""Initialize the stats handler with authentication."""
self.auth: audible.Authenticator | None = None
self.client: audible.Client | None = None
self.home = Path.home()
def authenticate(self) -> None:
"""Authenticate with Audible and store auth and client."""
auth_path = self.home / ".config" / "auditui" / "auth.json"
auth_path.parent.mkdir(parents=True, exist_ok=True)
if auth_path.exists():
try:
self.auth = audible.Authenticator.from_file(str(auth_path))
self.client = audible.Client(auth=self.auth)
return
except Exception:
logger.info("Failed to load existing auth. Re-authenticating.\n")
email = input("Email: ")
password = getpass("Password: ")
marketplace = (
input("Marketplace locale (default: US): ").strip().upper() or "US"
)
self.auth = audible.Authenticator.from_login(
username=email, password=password, locale=marketplace
)
self.auth.to_file(str(auth_path))
self.client = audible.Client(auth=self.auth)
def main() -> None:
"""Main entry point."""
stats = AudibleStats()
stats.authenticate()
if __name__ == "__main__":
main()