def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' self._log("%s:get_installed_books()" % self.app_name) self.installed_books = [] self.device = self.opts.gui.device_manager.device path_map = self.get_path_map() # Get books added to Kindle by calibre resolved_path_map = self._get_installed_books(path_map) # Add books added to Kindle by WhisperNet or download resolved_path_map = self._get_imported_books(resolved_path_map) self.books_db = self.generate_books_db_name(self.app_name_, self.opts.device_name) installed_books = set([]) # Used by get_active_annotations() to look up metadata based on title self.installed_books_by_title = {} # Create the books table self.create_books_table(self.books_db) # Initialize the progress bar self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) self.opts.pb.show() self.opts.pb.set_maximum(len(resolved_path_map)) # Add installed books to the database for book_id in resolved_path_map: try: mi = self._get_metadata(resolved_path_map[book_id]) except Exception as e: self._log("Unable to get metadata from book. path='%s'" % (resolved_path_map[book_id])) self._log(" Exception thrown was=%s" % (str(e))) continue self._log("Book on device title: '%s'" % (mi.title)) if 'News' in mi.tags: if not self.collect_news_clippings: continue installed_books.add(self.news_clippings_cid) else: installed_books.add(book_id) #self._log(mi.standard_field_keys()) # Populate a BookStruct with available metadata book_mi = BookStruct() book_mi.path = resolved_path_map[book_id] # Required items book_mi.active = True # Massage last, first authors back to normalcy book_mi.author = '' for i, author in enumerate(mi.authors): this_author = author.split(', ') this_author.reverse() book_mi.author += ' '.join(this_author) if i < len(mi.authors) - 1: book_mi.author += ' & ' book_mi.book_id = book_id book_mi.reader_app = self.app_name book_mi.title = mi.title.strip() # Optional items if mi.tags: book_mi.genre = ', '.join([tag for tag in mi.tags]) if 'News' in mi.tags: book_mi.book_id = self.news_clippings_cid if hasattr(mi, 'author_sort'): book_mi.author_sort = mi.author_sort if hasattr(mi, 'title_sort'): book_mi.title_sort = mi.title_sort else: book_mi.title_sort = re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', mi.title).rstrip() if hasattr(mi, 'uuid'): book_mi.uuid = mi.uuid # Add book to self.books_db self.add_to_books_db(self.books_db, book_mi) # Add book to indexed_books self.installed_books_by_title[mi.title.strip()] = {'book_id': book_id, 'author_sort': mi.author_sort} # Increment the progress bar self.opts.pb.increment() self.opts.pb.hide() # Update the timestamp self.update_timestamp(self.books_db) self.commit() self.installed_books = list(installed_books)
def get_installed_books(self): ''' For each book, construct a BookStruct object with the book's metadata. Starred items are minimally required. BookStruct properties: *active: [True|False] *author: "John Smith" author_sort: (if known) *book_id: an int uniquely identifying the book. Highlights are associated with books through book_id genre: "Fiction" (if known) *reader_app: self.app_name *title: "The Story of John Smith" title_sort: "Story of John Smith, The" (if known) uuid: Calibre's uuid for this book, if known ''' self._log("%s:get_installed_books()" % self.app_name) self.opts.pb.set_label("Getting installed books from %s" % self.app_name) self.opts.pb.set_value(0) db_profile = self._localize_database_path(self.app_id, self.books_subpath) self.book_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) if self.opts.disable_caching or not self._cache_is_current( db_profile['stats'], cached_db): self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the ios container self.ios.mount_ios_app(app_id=self.app_id) installed_books = set([]) self.tocs = {} # Create the books table as needed self.create_books_table(cached_db) con = sqlite3.connect(self.books_db) with con: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute('''SELECT DISTINCT author, oid, subject, source, title, uuidstr FROM book JOIN book_subjects ON book.oid = book_subjects.book_oid ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() book_id = row[b'oid'] installed_books.add(book_id) path = self._get_stanza_path(row[b'title']) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'author'] b_mi.book_id = book_id b_mi.genre = row[b'subject'] b_mi.path = path b_mi.title = row[b'title'] b_mi.uuid = self._get_uuid(row[b'uuidstr']) # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence cid, confidence = self.parent.generate_confidence(b_mi) toc_entries = None if confidence >= 2: toc_entries = self._get_epub_toc(cid=cid, path=path) elif path is not None: toc_entries = self._get_epub_toc(path=path) self.tocs[book_id] = toc_entries # Update the timestamp self.update_timestamp(cached_db) self.commit() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books