diff --git a/main.py b/main.py index d0f3ec5..96fb4ee 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,4 @@ +import alive_progress import requests import connectors import argparse @@ -29,6 +30,8 @@ class BookCollection(dict): keys = expand_range(sequence) for key in keys: + if not args.non_series and not float(key).is_integer(): + continue self.setdefault(key, []) self[key].append(book.asin) @@ -55,39 +58,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 @@ -150,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 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) @@ -168,7 +153,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 @@ -186,13 +173,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 and args.oncoming: 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 = [] @@ -208,15 +212,29 @@ def main(): msg, ) - # TODO: add input to choose which library is to be scaned - break - if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("-d", "--dev", action="store_true") - parser.add_argument("-v", "--verbose", 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() @@ -239,6 +257,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() 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 diff --git a/requirements.txt b/requirements.txt index ae6ebb6..acfe6f7 100644 Binary files a/requirements.txt and b/requirements.txt differ