def process_updates(self): ''' ''' self._log_location() db_folder = self._get_folder_location() if db_folder: sub_folder = os.path.join(db_folder, 'Metadata') updates = glob.glob(os.path.join(sub_folder, '*.xml')) if os.path.exists(sub_folder) and updates: self._log("processing Marvin Dropbox folder at '{0}'".format( db_folder)) pb = ProgressBar(parent=self.opts.gui, window_title="Processing Dropbox updates", on_top=True) total_books = len(updates) pb.set_maximum(total_books) pb.set_value(0) pb.show() for update in updates: with file(update) as f: doc = etree.fromstring(f.read()) if doc.tag == "metadatasnapshot" and doc.attrib[ 'creator'] == "Marvin": book = doc.xpath('//book')[0] title = book.attrib['title'] pb.set_label('{:^100}'.format("{0}".format(title))) pb.increment() cid = self._find_in_calibre_db(book) if cid: # *** Are we going to care about who's most recent? c_last_modified = self._get_calibre_last_modified( cid) m_last_modified = self._get_marvin_last_modified( book) if c_last_modified > m_last_modified: self._log("calibre metadata is newer") elif m_last_modified > c_last_modified: self._log("Marvin metadata is newer") self._update_calibre_metadata(book, cid) self._log( "*** Deleting metadata update record: NOT IMPLEMENTED ***" ) #os.remove(update) Application.processEvents() time.sleep(1.0) pb.hide() del pb updateCalibreGUIView() else: self._log("No MAX updates found")
def process_updates(self): ''' ''' self._log_location() db_folder = self._get_folder_location() if db_folder: sub_folder = os.path.join(db_folder, 'Metadata') updates = glob.glob(os.path.join(sub_folder, '*.xml')) if os.path.exists(sub_folder) and updates: self._log("processing Marvin Dropbox folder at '{0}'".format(db_folder)) pb = ProgressBar(parent=self.opts.gui, window_title="Processing Dropbox updates", on_top=True) total_books = len(updates) pb.set_maximum(total_books) pb.set_value(0) pb.show() for update in updates: with file(update) as f: doc = etree.fromstring(f.read()) if doc.tag == "metadatasnapshot" and doc.attrib['creator'] == "Marvin": book = doc.xpath('//book')[0] title = book.attrib['title'] pb.set_label('{:^100}'.format("{0}".format(title))) pb.increment() cid = self._find_in_calibre_db(book) if cid: # *** Are we going to care about who's most recent? c_last_modified = self._get_calibre_last_modified(cid) m_last_modified = self._get_marvin_last_modified(book) if c_last_modified > m_last_modified: self._log("calibre metadata is newer") elif m_last_modified > c_last_modified: self._log("Marvin metadata is newer") self._update_calibre_metadata(book, cid) self._log("*** Deleting metadata update record: NOT IMPLEMENTED ***") #os.remove(update) Application.processEvents() time.sleep(1.0) pb.hide() del pb updateCalibreGUIView() else: self._log("No MAX updates found")
def get_installed_books(self): """ Fetch installed books from mainDb.sqlite or cached_db Populate self.tocs: {book_id: {toc_entries} ...} """ 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.books_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): # (Re)load installed books from device 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 Author, AuthorSort, Title, CalibreTitleSort, FileName, Books.ID AS id_, UUID FROM Books ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_Marvin_path(row[b'FileName']) book_id = row[b'id_'] # Get the genre(s) for this book genre_cur = con.cursor() genre_cur.execute("""SELECT Subject FROM BookSubjects WHERE BookID = '{0}' """.format(book_id)) genres = None genre_rows = genre_cur.fetchall() if genre_rows is not None: genres = ', '.join( [genre[b'Subject'] for genre in genre_rows]) genre_cur.close() if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'Author'] b_mi.author_sort = row[b'AuthorSort'] b_mi.book_id = book_id b_mi.genre = genres b_mi.title = row[b'Title'] b_mi.title_sort = row[b'CalibreTitleSort'] b_mi.uuid = row[b'UUID'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc( path=path, prepend_title=b_mi.title) else: cid, confidence = self.parent.generate_confidence(b_mi) 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() self.ios.disconnect_idevice() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): """ Fetch installed books from iBooks_*.sqlite or cache """ 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.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) # Test timestamp against cached value if self.opts.disable_caching or not self._cache_is_current( db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the Media folder self.ios.mount_ios_media_folder() 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 ZASSETURL, ZBOOKAUTHOR, ZSORTAUTHOR, ZBOOKTITLE, ZSORTTITLE, ZDATABASEKEY FROM ZBKBOOKINFO WHERE ZASSETURL LIKE 'file://localhost%' AND ZASSETURL LIKE '%.epub/' ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_iBooks_path(row[b'ZASSETURL']) mi = self._get_metadata(path, row[b'ZBOOKTITLE']) genres = mi['genre'].split(', ') if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True book_id = row[b'ZDATABASEKEY'] installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'ZBOOKAUTHOR'] b_mi.author_sort = row[b'ZSORTAUTHOR'] b_mi.book_id = book_id b_mi.genre = mi['genre'] b_mi.title = row[b'ZBOOKTITLE'] b_mi.title_sort = row[b'ZSORTTITLE'] b_mi.uuid = mi['uuid'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc( path=path, prepend_title=b_mi.title) elif self.ios.exists(path): cid, confidence = self.parent.generate_confidence(b_mi) 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() self.ios.dismount_ios_media_folder() installed_books = list(installed_books) else: self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): """ Fetch installed books from mainDb.sqlite or cached_db Populate self.tocs: {book_id: {toc_entries} ...} """ 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.books_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): # (Re)load installed books from device 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 Author, AuthorSort, Title, CalibreTitleSort, FileName, Books.ID AS id_, UUID FROM Books ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_Marvin_path(row[b'FileName']) book_id = row[b'id_'] # Get the genre(s) for this book genre_cur = con.cursor() genre_cur.execute("""SELECT Subject FROM BookSubjects WHERE BookID = '{0}' """.format(book_id)) genres = None genre_rows = genre_cur.fetchall() if genre_rows is not None: genres = ', '.join([genre[b'Subject'] for genre in genre_rows]) genre_cur.close() if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'Author'] b_mi.author_sort = row[b'AuthorSort'] b_mi.book_id = book_id b_mi.genre = genres b_mi.title = row[b'Title'] b_mi.title_sort = row[b'CalibreTitleSort'] b_mi.uuid = row[b'UUID'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc(path=path, prepend_title=b_mi.title) else: cid, confidence = self.parent.generate_confidence(b_mi) 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() self.ios.disconnect_idevice() installed_books = list(installed_books) else: # Load installed books from cache self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books
def get_installed_books(self): """ Fetch installed books from iBooks_*.sqlite or cache """ 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.books_db = db_profile['path'] cached_db = self.generate_books_db_name(self.app_name_, self.ios.device_name) # Test timestamp against cached value if self.opts.disable_caching or not self._cache_is_current(db_profile['stats'], cached_db): # (Re)load installed books from device self._log(" fetching installed books from %s on %s" % (self.app_name, self.ios.device_name)) # Mount the Media folder self.ios.mount_ios_media_folder() 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 ZASSETURL, ZBOOKAUTHOR, ZSORTAUTHOR, ZBOOKTITLE, ZSORTTITLE, ZDATABASEKEY FROM ZBKBOOKINFO WHERE ZASSETURL LIKE 'file://localhost%' AND ZASSETURL LIKE '%.epub/' ''') rows = cur.fetchall() self.opts.pb.set_maximum(len(rows)) for row in rows: self.opts.pb.increment() this_is_news = False path = self._fix_iBooks_path(row[b'ZASSETURL']) mi = self._get_metadata(path, row[b'ZBOOKTITLE']) genres = mi['genre'].split(', ') if 'News' in genres: if not self.collect_news_clippings: continue this_is_news = True book_id = row[b'ZDATABASEKEY'] installed_books.add(book_id) # Populate a BookStruct b_mi = BookStruct() b_mi.active = True b_mi.author = row[b'ZBOOKAUTHOR'] b_mi.author_sort = row[b'ZSORTAUTHOR'] b_mi.book_id = book_id b_mi.genre = mi['genre'] b_mi.title = row[b'ZBOOKTITLE'] b_mi.title_sort = row[b'ZSORTTITLE'] b_mi.uuid = mi['uuid'] # Add book to books_db self.add_to_books_db(cached_db, b_mi) # Get the library cid, confidence toc_entries = None if this_is_news: cid = self.news_clippings_cid confidence = 5 if path is not None: toc_entries = self._get_epub_toc(path=path, prepend_title=b_mi.title) elif self.ios.exists(path): cid, confidence = self.parent.generate_confidence(b_mi) 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() self.ios.dismount_ios_media_folder() installed_books = list(installed_books) else: self._log(" retrieving cached books from %s" % cached_db) self.opts.pb.set_maximum(2) self.opts.pb.set_value(1) Application.processEvents() installed_books = self._get_cached_books(cached_db) self.installed_books = installed_books