def GetAllBooks(user: User, outputPath: str) -> None: kobo = Kobo(user) kobo.LoadInitializationSettings() bookList = kobo.GetMyBookList() for entitlement in bookList: newEntitlement = entitlement.get("NewEntitlement") if newEntitlement is None: continue try: bookMetadata = newEntitlement["BookMetadata"] except Exception: # skip audiobooks continue fileName = __MakeFileNameForBook(bookMetadata) outputFilePath = os.path.join(outputPath, fileName) # Skip archived books. if __IsBookArchived(newEntitlement): title = bookMetadata["Title"] author = __GetBookAuthor(bookMetadata) if len(author) > 0: title += " by " + author click.echo(f"Skipping archived book {title}") continue try: output = kobo.Download(bookMetadata["RevisionId"], outputFilePath) click.echo(f"Downloaded to {output}", err=True) except Exception as e: click.echo("could not download".format(bookMetadata["Title"])) click.echo(e)
def GetBookOrBooks(user: User, outputPath: str, productId: str = '') -> Union[None, str]: ''' download 1 or all books to file returns output filepath if identifier is passed, otherwise returns None ''' outputPath = os.path.abspath(outputPath) kobo = Kobo(user) kobo.LoadInitializationSettings() # Must call GetBookList every time, even if you're only getting 1 book, # because it invokes a library sync endpoint. # This is the only known endpoint that returns # download URLs along with book metadata. bookList = kobo.GetMyBookList() for entitlement in bookList: newEntitlement = entitlement.get('NewEntitlement') if newEntitlement is None: continue bookMetadata, book_type = __GetBookMetadata(newEntitlement) if book_type is None: click.echo('Skipping book of unknown type') continue elif book_type == BookType.SUBSCRIPTION: click.echo('Skipping subscribtion entity') continue fileName = __MakeFileNameForBook(bookMetadata) if book_type == BookType.EBOOK: # Audiobooks go in sub-directories # but epub files go directly in outputPath fileName += '.epub' outputFilePath = os.path.join(outputPath, fileName) if not productId and os.path.exists(outputFilePath): # when downloading ALL books, skip books we've downloaded before click.echo(f'Skipping already downloaded book {outputFilePath}') continue if productId and productId != Kobo.GetProductId(bookMetadata): # user only asked for a single title, # and this is not the book they want continue # Skip archived books. if __IsBookArchived(newEntitlement): click.echo(f'Skipping archived book {fileName}') continue kobo.Download(bookMetadata, book_type == BookType.AUDIOBOOK, outputFilePath) click.echo(f'Downloaded {productId} to {outputFilePath}', err=True) if productId: # TODO: support audiobook downloads from web return outputFilePath return None
def __GetBookList(kobo: Kobo, listAll: bool, exportFile: Union[TextIO, None]) -> list: bookList = kobo.GetMyBookList() rows = [] if exportFile: exportFile.write(json.dumps(bookList, indent=2)) for entitlement in bookList: newEntitlement = entitlement.get('NewEntitlement') if newEntitlement is None: continue bookEntitlement = newEntitlement.get('BookEntitlement') if bookEntitlement is not None: # Skip saved previews. if bookEntitlement.get('Accessibility') == 'Preview': continue # Skip refunded books. if bookEntitlement.get('IsLocked'): continue if (not listAll) and __IsBookRead(newEntitlement): continue bookMetadata, book_type = __GetBookMetadata(newEntitlement) if book_type is None: click.echo('Skipping book of unknown type') continue elif book_type in SUPPORTED_BOOK_TYPES: book = [ bookMetadata['RevisionId'], bookMetadata['Title'], __GetBookAuthor(bookMetadata), __IsBookArchived(newEntitlement), book_type == BookType.AUDIOBOOK, ] rows.append(book) rows = sorted(rows, key=lambda columns: columns[1].lower()) return rows
def __GetBookList(kobo: Kobo, listAll: bool) -> list: bookList = kobo.GetMyBookList() rows = [] for entitlement in bookList: newEntitlement = entitlement.get("NewEntitlement") if newEntitlement is None: continue bookEntitlement = newEntitlement.get("BookEntitlement") if bookEntitlement is not None: # Skip saved previews. if bookEntitlement.get("Accessibility") == "Preview": continue # Skip refunded books. if bookEntitlement.get("IsLocked"): continue if (not listAll) and __IsBookRead(newEntitlement): continue try: bookMetadata = newEntitlement["BookMetadata"] except Exception as e: # skip audiobook continue book = [ bookMetadata["RevisionId"], bookMetadata["Title"], __GetBookAuthor(bookMetadata), __IsBookArchived(newEntitlement), ] rows.append(book) rows = sorted(rows, key=lambda columns: columns[1].lower()) return rows
def GetBookOrBooks(user: User, outputPath: str, productId: str = '') -> Union[None, str]: """ download 1 or all books to file returns output filepath if identifier is passed, otherwise returns None """ outputPath = os.path.abspath(outputPath) kobo = Kobo(user) kobo.LoadInitializationSettings() # Must call GetBookList every time, even if you're only getting 1 book, # because it invokes a library sync endpoint. # This is the only known endpoint that returns # download URLs along with book metadata. bookList = kobo.GetMyBookList() for entitlement in bookList: newEntitlement = entitlement.get('NewEntitlement') if newEntitlement is None: continue bookMetadata, book_type = __GetBookMetadata(newEntitlement) if book_type is None: click.echo('Skipping book of unknown type') continue elif book_type == BookType.SUBSCRIPTION: click.echo('Skipping subscribtion entity') continue fileName = __MakeFileNameForBook(bookMetadata) if book_type == BookType.EBOOK: # Audiobooks go in sub-directories # but epub files go directly in outputPath fileName += '.epub' outputFilePath = os.path.join(outputPath, fileName) if not productId and os.path.exists(outputFilePath): # when downloading ALL books, skip books we've downloaded before click.echo(f'Skipping already downloaded book {outputFilePath}') continue currentProductId = Kobo.GetProductId(bookMetadata) if productId and productId != currentProductId: # user only asked for a single title, # and this is not the book they want continue # Skip archived books. if __IsBookArchived(newEntitlement): click.echo(f'Skipping archived book {fileName}') continue try: click.echo(f'Downloading {currentProductId} to {outputFilePath}', err=True) kobo.Download(bookMetadata, book_type == BookType.AUDIOBOOK, outputFilePath) except KoboException as e: if productId: raise e else: click.echo( (f'Skipping failed download for {currentProductId}: {str(e)}' '\n -- Try downloading it as a single book to get the complete exception details' ' and open an issue on the project GitHub page: https://github.com/subdavis/kobo-book-downloader/issues' ), err=True, ) if productId: # TODO: support audiobook downloads from web return outputFilePath return None