Compare commits

...

5 commits

3 changed files with 66 additions and 38 deletions

96
main.py
View file

@ -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()

View file

@ -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

Binary file not shown.