import argparse import sqlite3 from os.path import exists, dirname, join, isfile import sys parser = argparse.ArgumentParser() parser.add_argument("mount_point", help="Directory/Mount point of your Tolino device", type=str) parser.add_argument("-n", "--dry-run", help="Don't change database; show information only.", action="store_true") args = parser.parse_args() if not exists(args.mount_point): print("Directory/Mount point does not exist. Exiting.") sys.exit(1) dir_path = dirname(args.mount_point) version_file = join(dir_path, ".kobo", "version") device_version_info = "" if isfile(version_file): with open(version_file) as vf: device_version_info = vf.read().strip().split(",") else: print("No device information found. Please sprecify the database file directly on the device.\nExiting.") sys.exit(1) device_model_id = device_version_info[-1] if device_model_id.endswith("691"): print("Tolino Shine 5 found.") elif device_model_id.endswith("693"): print("Tolino Shine Color found.") elif device_model_id.endswith("690"): print("Tolino Vision Color found.") else: print("No supported Tolino device found. Exiting.") sys.exit(1) dbfile = join(dir_path, ".kobo", "KoboReader.sqlite") con = sqlite3.connect(dbfile) cur = con.cursor() res = cur.execute("SELECT version FROM DbVersion") item = res.fetchone() if item is None: print("No valid database file. Exiting.") sys.exit(1) version = item[0] if version < 188: print("Database version unsupported. Exiting.") sys.exit(1) res = cur.execute("SELECT Id FROM Shelf WHERE (_IsDeleted <> true AND _IsDeleted <> false) OR (_IsVisible <> true AND _IsVisible <> false) OR (_IsSynced <> true AND _IsSynced <> false)") items_shelf = res.fetchall() res = cur.execute("SELECT ShelfName, ContentId FROM ShelfContent WHERE (_IsDeleted <> true AND _IsDeleted <> false) OR (_IsSynced <> true AND _IsSynced <> false)") items_shelf_content = res.fetchall() if len(items_shelf) == 0: print("No affected entries in table Shelf.") else: print("Affected entries in table Shelf:") for item in items_shelf: print(f"- {item[0]}") if len(items_shelf_content) == 0: print("No affected entries in table ShelfContent.") else: print("Affected entries in table Shelf:") for item in items_shelf_content: print(f"- {item[0]} with ContentId {item[1]}") if len(items_shelf) == 0 and len(items_shelf_content) == 0: print("Database is ok.") sys.exit(0) if len(items_shelf) > 0 and not args.dry_run: print("Fixing table 'Shelf' ...") cur.execute("UPDATE Shelf SET _IsDeleted = true WHERE _IsDeleted = 'true'") cur.execute("UPDATE Shelf SET _IsVisible = true WHERE _IsVisible = 'true'") cur.execute("UPDATE Shelf SET _IsSynced = true WHERE _IsSynced = 'true'") cur.execute("UPDATE Shelf SET _IsDeleted = false WHERE _IsDeleted = 'false'") cur.execute("UPDATE Shelf SET _IsVisible = false WHERE _IsVisible = 'false'") cur.execute("UPDATE Shelf SET _IsSynced = false WHERE _IsSynced = 'false'") con.commit() if len(items_shelf_content) > 0 and not args.dry_run: print("Fixing table 'ShelfContent' ...") cur.execute("UPDATE ShelfContent SET _IsDeleted = true WHERE _IsDeleted = 'true'") cur.execute("UPDATE ShelfContent SET _IsSynced = true WHERE _IsSynced = 'true'") cur.execute("UPDATE ShelfContent SET _IsDeleted = false WHERE _IsDeleted = 'false'") cur.execute("UPDATE ShelfContent SET _IsSynced = false WHERE _IsSynced = 'false'") con.commit() if not args.dry_run: print("Done.")