216 lines
8.5 KiB
Python
216 lines
8.5 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
# This is a simple tool to identify all Amazon Topaz ebooks in a specific directory.
|
||
|
# There always seems to be confusion since Topaz books downloaded to K4PC/Mac can have
|
||
|
# almost any extension (.azw, .azw1, .prc, tpz). While the .azw1 and .tpz extensions
|
||
|
# are fairly easy to indentify, the others are not (without opening the files in an editor).
|
||
|
|
||
|
# To run the tool with the GUI frontend, just double-click on the 'FindTopazFiles.pyw' file
|
||
|
# and select the folder where all of the ebooks in question are located. Then click 'Search'.
|
||
|
# The program will list the file names of the ebooks that are indentified as being Topaz.
|
||
|
# You can then isolate those books and use the Topaz tools to decrypt and convert them.
|
||
|
|
||
|
# You can also run the script from a command line... supplying the folder to search
|
||
|
# as a parameter: python FindTopazEbooks.pyw "C:\My Folder" (change appropriately for
|
||
|
# your particular O.S.)
|
||
|
|
||
|
# ** NOTE: This program does NOT decrypt or modify Topaz files in any way. It simply identifies them.
|
||
|
|
||
|
# PLEASE DO NOT PIRATE EBOOKS!
|
||
|
|
||
|
# We want all authors and publishers, and eBook stores to live
|
||
|
# long and prosperous lives but at the same time we just want to
|
||
|
# be able to read OUR books on whatever device we want and to keep
|
||
|
# readable for a long, long time
|
||
|
|
||
|
# This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle,
|
||
|
# unswindle, DarkReverser, ApprenticeAlf, DiapDealer, some_updates
|
||
|
# and many many others
|
||
|
|
||
|
# Revision history:
|
||
|
# 1 - Initial release.
|
||
|
|
||
|
from __future__ import with_statement
|
||
|
|
||
|
__license__ = 'GPL v3'
|
||
|
|
||
|
import sys
|
||
|
import os
|
||
|
import re
|
||
|
import shutil
|
||
|
import Tkinter
|
||
|
import Tkconstants
|
||
|
import tkFileDialog
|
||
|
import tkMessageBox
|
||
|
|
||
|
|
||
|
class ScrolledText(Tkinter.Text):
|
||
|
def __init__(self, master=None, **kw):
|
||
|
self.frame = Tkinter.Frame(master)
|
||
|
self.vbar = Tkinter.Scrollbar(self.frame)
|
||
|
self.vbar.pack(side=Tkconstants.RIGHT, fill=Tkconstants.Y)
|
||
|
kw.update({'yscrollcommand': self.vbar.set})
|
||
|
Tkinter.Text.__init__(self, self.frame, **kw)
|
||
|
self.pack(side=Tkconstants.LEFT, fill=Tkconstants.BOTH, expand=True)
|
||
|
self.vbar['command'] = self.yview
|
||
|
# Copy geometry methods of self.frame without overriding Text
|
||
|
# methods = hack!
|
||
|
text_meths = vars(Tkinter.Text).keys()
|
||
|
methods = vars(Tkinter.Pack).keys() + vars(Tkinter.Grid).keys() + vars(Tkinter.Place).keys()
|
||
|
methods = set(methods).difference(text_meths)
|
||
|
for m in methods:
|
||
|
if m[0] != '_' and m != 'config' and m != 'configure':
|
||
|
setattr(self, m, getattr(self.frame, m))
|
||
|
|
||
|
def __str__(self):
|
||
|
return str(self.frame)
|
||
|
|
||
|
|
||
|
def cli_main(argv=sys.argv, obj=None):
|
||
|
progname = os.path.basename(argv[0])
|
||
|
if len(argv) != 2:
|
||
|
print "usage: %s DIRECTORY" % (progname,)
|
||
|
return 1
|
||
|
|
||
|
if obj == None:
|
||
|
print "\nTopaz search results:\n"
|
||
|
else:
|
||
|
obj.stext.insert(Tkconstants.END,"Topaz search results:\n\n")
|
||
|
|
||
|
inpath = argv[1]
|
||
|
files = os.listdir(inpath)
|
||
|
filefilter = re.compile("(\.azw$)|(\.azw1$)|(\.prc$)|(\.tpz$)", re.IGNORECASE)
|
||
|
files = filter(filefilter.search, files)
|
||
|
|
||
|
if files:
|
||
|
topazcount = 0
|
||
|
totalcount = 0
|
||
|
for filename in files:
|
||
|
with open(os.path.join(inpath, filename), 'rb') as f:
|
||
|
try:
|
||
|
if f.read().startswith('TPZ'):
|
||
|
f.close()
|
||
|
basename, extension = os.path.splitext(filename)
|
||
|
if obj == None:
|
||
|
print " %s is a Topaz formatted ebook." % filename
|
||
|
"""
|
||
|
if extension == '.azw' or extension == '.prc':
|
||
|
print " renaming to %s" % (basename + '.tpz')
|
||
|
shutil.move(os.path.join(inpath, filename),
|
||
|
os.path.join(inpath, basename + '.tpz'))
|
||
|
"""
|
||
|
else:
|
||
|
msg1 = " %s is a Topaz formatted ebook.\n" % filename
|
||
|
obj.stext.insert(Tkconstants.END,msg1)
|
||
|
"""
|
||
|
if extension == '.azw' or extension == '.prc':
|
||
|
msg2 = " renaming to %s\n" % (basename + '.tpz')
|
||
|
obj.stext.insert(Tkconstants.END,msg2)
|
||
|
shutil.move(os.path.join(inpath, filename),
|
||
|
os.path.join(inpath, basename + '.tpz'))
|
||
|
"""
|
||
|
topazcount += 1
|
||
|
except:
|
||
|
if obj == None:
|
||
|
print " Error reading %s." % filename
|
||
|
else:
|
||
|
msg = " Error reading or %s.\n" % filename
|
||
|
obj.stext.insert(Tkconstants.END,msg)
|
||
|
pass
|
||
|
totalcount += 1
|
||
|
if topazcount == 0:
|
||
|
if obj == None:
|
||
|
print "\nNo Topaz books found in %s." % inpath
|
||
|
else:
|
||
|
msg = "\nNo Topaz books found in %s.\n\n" % inpath
|
||
|
obj.stext.insert(Tkconstants.END,msg)
|
||
|
else:
|
||
|
if obj == None:
|
||
|
print "\n%i Topaz books found in %s\n%i total books checked.\n" % (topazcount, inpath, totalcount)
|
||
|
else:
|
||
|
msg = "\n%i Topaz books found in %s\n%i total books checked.\n\n" %(topazcount, inpath, totalcount)
|
||
|
obj.stext.insert(Tkconstants.END,msg)
|
||
|
else:
|
||
|
if obj == None:
|
||
|
print "No typical Topaz file extensions found in %s.\n" % inpath
|
||
|
else:
|
||
|
msg = "No typical Topaz file extensions found in %s.\n\n" % inpath
|
||
|
obj.stext.insert(Tkconstants.END,msg)
|
||
|
|
||
|
return 0
|
||
|
|
||
|
|
||
|
class DecryptionDialog(Tkinter.Frame):
|
||
|
def __init__(self, root):
|
||
|
Tkinter.Frame.__init__(self, root, border=5)
|
||
|
ltext='Search a directory for Topaz eBooks\n'
|
||
|
self.status = Tkinter.Label(self, text=ltext)
|
||
|
self.status.pack(fill=Tkconstants.X, expand=1)
|
||
|
body = Tkinter.Frame(self)
|
||
|
body.pack(fill=Tkconstants.X, expand=1)
|
||
|
sticky = Tkconstants.E + Tkconstants.W
|
||
|
body.grid_columnconfigure(1, weight=2)
|
||
|
Tkinter.Label(body, text='Directory to Search').grid(row=1)
|
||
|
self.inpath = Tkinter.Entry(body, width=30)
|
||
|
self.inpath.grid(row=1, column=1, sticky=sticky)
|
||
|
button = Tkinter.Button(body, text="...", command=self.get_inpath)
|
||
|
button.grid(row=1, column=2)
|
||
|
msg1 = 'Topaz search results \n\n'
|
||
|
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE,
|
||
|
height=15, width=60, wrap=Tkconstants.WORD)
|
||
|
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
|
||
|
#self.stext.insert(Tkconstants.END,msg1)
|
||
|
buttons = Tkinter.Frame(self)
|
||
|
buttons.pack()
|
||
|
|
||
|
|
||
|
self.botton = Tkinter.Button(
|
||
|
buttons, text="Search", width=10, command=self.search)
|
||
|
self.botton.pack(side=Tkconstants.LEFT)
|
||
|
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
|
||
|
self.button = Tkinter.Button(
|
||
|
buttons, text="Quit", width=10, command=self.quit)
|
||
|
self.button.pack(side=Tkconstants.RIGHT)
|
||
|
|
||
|
def get_inpath(self):
|
||
|
cwd = os.getcwdu()
|
||
|
cwd = cwd.encode('utf-8')
|
||
|
inpath = tkFileDialog.askdirectory(
|
||
|
parent=None, title='Directory to search',
|
||
|
initialdir=cwd, initialfile=None)
|
||
|
if inpath:
|
||
|
inpath = os.path.normpath(inpath)
|
||
|
self.inpath.delete(0, Tkconstants.END)
|
||
|
self.inpath.insert(0, inpath)
|
||
|
return
|
||
|
|
||
|
|
||
|
def search(self):
|
||
|
inpath = self.inpath.get()
|
||
|
if not inpath or not os.path.exists(inpath):
|
||
|
self.status['text'] = 'Specified directory does not exist'
|
||
|
return
|
||
|
argv = [sys.argv[0], inpath]
|
||
|
self.status['text'] = 'Searching...'
|
||
|
self.botton.configure(state='disabled')
|
||
|
cli_main(argv, self)
|
||
|
self.status['text'] = 'Search a directory for Topaz files'
|
||
|
self.botton.configure(state='normal')
|
||
|
|
||
|
return
|
||
|
|
||
|
|
||
|
def gui_main():
|
||
|
root = Tkinter.Tk()
|
||
|
root.title('Topaz eBook Finder')
|
||
|
root.resizable(True, False)
|
||
|
root.minsize(370, 0)
|
||
|
DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1)
|
||
|
root.mainloop()
|
||
|
return 0
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
if len(sys.argv) > 1:
|
||
|
sys.exit(cli_main())
|
||
|
sys.exit(gui_main())
|