From 6e151a8d281a7a975dd251a625f56b085c59703e Mon Sep 17 00:00:00 2001 From: Yunn Xairou Date: Sat, 13 Sep 2025 19:38:52 +0200 Subject: [PATCH 1/5] Add alive_progress for enhanced series processing feedback --- main.py | 3 ++- requirements.txt | Bin 168 -> 214 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index d0f3ec5..010f34e 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,4 @@ +import alive_progress import requests import connectors import argparse @@ -152,7 +153,7 @@ def main(): for library in libraries: series = abs.get_series_by_library_id(library["id"]) - for serie in series: + for serie in alive_progress.alive_it(series): series_name = serie["name"] abs_book_sequence = process_abs_serie(serie["books"], series_name) diff --git a/requirements.txt b/requirements.txt index ae6ebb6eb812f9e419dae5bff8a49ddc8b18ec2e..acfe6f7efb0f28897bad859223df8974b30d5664 100644 GIT binary patch delta 53 zcmZ3%c#Uzw3O!y1E`~&g9EMDWGKN%!c!mOoB8Gg1bRe0^Pz;2&KxoXM2gU{r082~? APXGV_ delta 6 Ncmcb{xPo!Q3IGXu0=WPH From 043f57842a12f7f5950e5250c39bb4fa57e352fd Mon Sep 17 00:00:00 2001 From: Yunn Xairou Date: Sat, 13 Sep 2025 21:01:32 +0200 Subject: [PATCH 2/5] Refactor process_audible_serie to improve handling of non-series books and enhance logging for missing books --- main.py | 59 +++++++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/main.py b/main.py index 010f34e..deb09c7 100644 --- a/main.py +++ b/main.py @@ -56,39 +56,17 @@ def expand_range(part): return [] # Handle non-numeric input or invalid format -def process_sequence(books): - """Groups books by ASIN, handling sequence ranges (including floats).""" - books_sequence = {} - for book in books: - asin = book["asin"] - sequence = book.get("sequence", "") - - if sequence: - keys = expand_range(sequence.split(", ")[0]) - else: - keys = [float(book.get("sort", "1")) * -1] - - for key in keys: - if key not in books_sequence: - books_sequence[key] = [] - books_sequence[key].append(asin) - - keys = sorted(books_sequence.keys(), key=lambda x: float(x)) - ordered_sequence = {} - for key in keys: - ordered_sequence[key] = books_sequence[key] - return ordered_sequence - - def process_audible_serie(books, serie_name): processed_books = BookCollection(serie_name) for json in books: - if book["relationship_type"] == "series": + if json["relationship_type"] == "series": book = Book(json["asin"]) book.series.setdefault(serie_name, json["sequence"]) book.series.setdefault(serie_name, f"-{json['sort']}") processed_books.add(book) + else: + logger.debug("Skipping non-series book: %s", json["asin"]) return processed_books @@ -169,7 +147,9 @@ def main(): continue audible_serie = audible.get_produce_from_asin(series_asin) - audible_book_sequence = process_sequence(audible_serie["relationships"]) + audible_book_sequence = process_audible_serie( + audible_serie["relationships"], series_name + ) if len(abs_book_sequence) >= len(audible_book_sequence): continue @@ -187,13 +167,30 @@ def main(): soon_to_release_books = [] for key in missing_keys: - try: - audnexus.get_book_from_asin(audible_book_sequence[key][0]) - missing_books.append(key) + found = False + for asin in audible_book_sequence[key]: + try: + audnexus.get_book_from_asin(asin) + missing_books.append(key) + logger.debug( + "%s Book %.1f is missing - %s", + series_name, + key, + audible_book_sequence[key][0], + ) + found = True + break + except requests.exceptions.HTTPError: + pass - except requests.exceptions.HTTPError: - logger.debug("%s Book %d is yet to be released", series_name, key) + if not found: soon_to_release_books.append(key) + logger.debug( + "%s Book %d is yet to be released - %s", + series_name, + key, + audible_book_sequence[key][0], + ) msgs = [] From 330554435d6d051b53d590e83a0d6f5b7079cb93 Mon Sep 17 00:00:00 2001 From: Yunn Xairou Date: Sat, 13 Sep 2025 21:10:45 +0200 Subject: [PATCH 3/5] Add --hors-series argument to skip non-integer series keys in BookCollection --- main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.py b/main.py index deb09c7..7e7de1b 100644 --- a/main.py +++ b/main.py @@ -30,6 +30,8 @@ class BookCollection(dict): keys = expand_range(sequence) for key in keys: + if not args.hors_series and not float(key).is_integer(): + continue self.setdefault(key, []) self[key].append(book.asin) @@ -215,6 +217,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-d", "--dev", action="store_true") parser.add_argument("-v", "--verbose", action="store_true") + parser.add_argument("--hors-series", action="store_true") args = parser.parse_args() From e31ae00528bf5a3c9a807f3096156775af2c0031 Mon Sep 17 00:00:00 2001 From: Yunn Xairou Date: Sat, 13 Sep 2025 21:18:44 +0200 Subject: [PATCH 4/5] Filter libraries in main to only process Audible books and enhance logging for clarity --- main.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 7e7de1b..198e35b 100644 --- a/main.py +++ b/main.py @@ -131,9 +131,13 @@ def main(): libraries = abs.get_library_ids() for library in libraries: - series = abs.get_series_by_library_id(library["id"]) + if library["mediaType"] != "book" or library["provider"] != "audible": + continue - for serie in alive_progress.alive_it(series): + logger.info("==== %s ====", library["name"]) + + series = abs.get_series_by_library_id(library["id"]) + for serie in alive_progress.alive_it(series, title=library["name"]): series_name = serie["name"] abs_book_sequence = process_abs_serie(serie["books"], series_name) @@ -208,9 +212,6 @@ def main(): msg, ) - # TODO: add input to choose which library is to be scaned - break - if __name__ == "__main__": @@ -240,6 +241,8 @@ if __name__ == "__main__": logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("httpcore").setLevel(logging.WARNING) + alive_progress.config_handler.set_global(enrich_print=False) + logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG if args.verbose else logging.INFO) main() From 329b076caf3c979a6ce3a94f0c1508a89aee18d4 Mon Sep 17 00:00:00 2001 From: Yunn Xairou Date: Sat, 13 Sep 2025 21:36:12 +0200 Subject: [PATCH 5/5] Update argument names and documentation for clarity in main.py and README.md --- main.py | 26 +++++++++++++++++++++----- readme.md | 8 ++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 198e35b..96fb4ee 100644 --- a/main.py +++ b/main.py @@ -30,7 +30,7 @@ class BookCollection(dict): keys = expand_range(sequence) for key in keys: - if not args.hors_series and not float(key).is_integer(): + if not args.non_series and not float(key).is_integer(): continue self.setdefault(key, []) self[key].append(book.asin) @@ -189,7 +189,7 @@ def main(): except requests.exceptions.HTTPError: pass - if not found: + if not found and args.oncoming: soon_to_release_books.append(key) logger.debug( "%s Book %d is yet to be released - %s", @@ -216,9 +216,25 @@ def main(): if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("-d", "--dev", action="store_true") - parser.add_argument("-v", "--verbose", action="store_true") - parser.add_argument("--hors-series", action="store_true") + # General flags + parser.add_argument( + "-v", "--verbose", action="store_true", help="Enable verbose logging" + ) + parser.add_argument( + "-d", "--dev", action="store_true", help="Use development/mock connectors" + ) + + # Feature-specific flags + parser.add_argument( + "--non-series", + action="store_true", + help="Include non-series books (books not part of a numbered series)", + ) + parser.add_argument( + "--oncoming", + action="store_true", + help="Show books to be released", + ) args = parser.parse_args() diff --git a/readme.md b/readme.md index dcc3aa2..864f010 100644 --- a/readme.md +++ b/readme.md @@ -32,6 +32,14 @@ python main.py Logs are written to the `log` file. +### Feature-specific Arguments + +- `--non-series` + Include non-series books (books not part of a numbered series). + +- `--oncoming` + Show books that are yet to be released. + ## Project Structure - [main.py](main.py): Entry point and main logic