Transit from optparse to argparse

This commit is contained in:
KnugiHK
2023-02-13 12:53:20 +08:00
parent 26320413e8
commit 9178e5326b
+61 -62
View File
@@ -6,7 +6,7 @@ from Whatsapp_Chat_Exporter import extract_new as extract
from Whatsapp_Chat_Exporter import extract_iphone from Whatsapp_Chat_Exporter import extract_iphone
from Whatsapp_Chat_Exporter import extract_iphone_media from Whatsapp_Chat_Exporter import extract_iphone_media
from Whatsapp_Chat_Exporter.extract_new import Crypt from Whatsapp_Chat_Exporter.extract_new import Crypt
from optparse import OptionParser from argparse import ArgumentParser
import os import os
import sqlite3 import sqlite3
import shutil import shutil
@@ -16,135 +16,141 @@ from sys import exit
def main(): def main():
parser = OptionParser(version=f"Whatsapp Chat Exporter: {__version__}") parser = ArgumentParser(
parser.add_option( description = 'A customizable Android and iPhone WhatsApp database parser that '
'will give you the history of your WhatsApp conversations inHTML '
'and JSON. Android Backup Crypt12, Crypt14 and Crypt15 supported.',
epilog = f'WhatsApp Chat Exporter: {__version__} Licensed with MIT'
)
parser.add_argument(
'-a', '-a',
'--android', '--android',
dest='android', dest='android',
default=False, default=False,
action='store_true', action='store_true',
help="Define the target as Android") help="Define the target as Android")
parser.add_option( parser.add_argument(
'-i', '-i',
'--iphone', '--iphone',
dest='iphone', dest='iphone',
default=False, default=False,
action='store_true', action='store_true',
help="Define the target as iPhone") help="Define the target as iPhone")
parser.add_option( parser.add_argument(
"-w", "-w",
"--wa", "--wa",
dest="wa", dest="wa",
default=None, default=None,
help="Path to contact database") help="Path to contact database")
parser.add_option( parser.add_argument(
"-m", "-m",
"--media", "--media",
dest="media", dest="media",
default=None, default=None,
help="Path to WhatsApp media folder") help="Path to WhatsApp media folder")
parser.add_option( parser.add_argument(
"-b", "-b",
"--backup", "--backup",
dest="backup", dest="backup",
default=None, default=None,
help="Path to Android (must be used together " help="Path to Android (must be used together "
"with -k)/iPhone WhatsApp backup") "with -k)/iPhone WhatsApp backup")
parser.add_option( parser.add_argument(
"-o", "-o",
"--output", "--output",
dest="output", dest="output",
default="result", default="result",
help="Output to specific directory") help="Output to specific directory")
parser.add_option( parser.add_argument(
'-j', '-j',
'--json', '--json',
dest='json', dest='json',
default=False, default=False,
action='store_true', action='store_true',
help="Save the result to a single JSON file") help="Save the result to a single JSON file")
parser.add_option( parser.add_argument(
'-d', '-d',
'--db', '--db',
dest='db', dest='db',
default=None, default=None,
help="Path to database file") help="Path to database file")
parser.add_option( parser.add_argument(
'-k', '-k',
'--key', '--key',
dest='key', dest='key',
default=None, default=None,
help="Path to key file" help="Path to key file"
) )
parser.add_option( parser.add_argument(
"-t", "-t",
"--template", "--template",
dest="template", dest="template",
default=None, default=None,
help="Path to custom HTML template") help="Path to custom HTML template")
parser.add_option( parser.add_argument(
"-e", "-e",
"--embedded", "--embedded",
dest="embedded", dest="embedded",
default=False, default=False,
action='store_true', action='store_true',
help="Embed media into HTML file") help="Embed media into HTML file")
parser.add_option( parser.add_argument(
"-s", "-s",
"--showkey", "--showkey",
dest="showkey", dest="showkey",
default=False, default=False,
action='store_true', action='store_true',
help="Show the HEX key used to decrypt the database") help="Show the HEX key used to decrypt the database")
parser.add_option( parser.add_argument(
"-c", "-c",
"--move-media", "--move-media",
dest="move_media", dest="move_media",
default=False, default=False,
action='store_true', action='store_true',
help="Move the media directory to output directory if the flag is set, otherwise copy it") help="Move the media directory to output directory if the flag is set, otherwise copy it")
parser.add_option( parser.add_argument(
"--offline", "--offline",
dest="offline", dest="offline",
default=None, default=None,
help="Relative path to offline static files") help="Relative path to offline static files")
(options, args) = parser.parse_args() args = parser.parse_args()
if options.android and options.iphone: if args.android and args.iphone:
print("You must define only one device type.") print("You must define only one device type.")
exit(1) exit(1)
if not options.android and not options.iphone: if not args.android and not args.iphone:
print("You must define the device type.") print("You must define the device type.")
exit(1) exit(1)
data = {} data = {}
if options.android: if args.android:
contacts = extract.contacts contacts = extract.contacts
messages = extract.messages messages = extract.messages
media = extract.media media = extract.media
vcard = extract.vcard vcard = extract.vcard
create_html = extract.create_html create_html = extract.create_html
if options.db is None: if args.db is None:
msg_db = "msgstore.db" msg_db = "msgstore.db"
else: else:
msg_db = options.db msg_db = args.db
if options.key is not None: if args.key is not None:
if options.backup is None: if args.backup is None:
print("You must specify the backup file with -b") print("You must specify the backup file with -b")
exit(1) exit(1)
print("Decryption key specified, decrypting WhatsApp backup...") print("Decryption key specified, decrypting WhatsApp backup...")
if "crypt12" in options.backup: if "crypt12" in args.backup:
crypt = Crypt.CRYPT12 crypt = Crypt.CRYPT12
elif "crypt14" in options.backup: elif "crypt14" in args.backup:
crypt = Crypt.CRYPT14 crypt = Crypt.CRYPT14
elif "crypt15" in options.backup: elif "crypt15" in args.backup:
crypt = Crypt.CRYPT15 crypt = Crypt.CRYPT15
if os.path.isfile(options.key): if os.path.isfile(args.key):
key = open(options.key, "rb") key = open(args.key, "rb")
elif all(char in string.hexdigits for char in options.key): elif all(char in string.hexdigits for char in args.key):
key = bytes.fromhex(options.key) key = bytes.fromhex(args.key)
db = open(options.backup, "rb").read() db = open(args.backup, "rb").read()
error = extract.decrypt_backup(db, key, msg_db, crypt, options.showkey) error = extract.decrypt_backup(db, key, msg_db, crypt, args.showkey)
if error != 0: if error != 0:
if error == 1: if error == 1:
print("Dependencies of decrypt_backup and/or extract_encrypted_key" print("Dependencies of decrypt_backup and/or extract_encrypted_key"
@@ -157,72 +163,65 @@ def main():
else: else:
print("Unknown error occurred.", error) print("Unknown error occurred.", error)
exit(5) exit(5)
if options.wa is None: if args.wa is None:
contact_db = "wa.db" contact_db = "wa.db"
else: else:
contact_db = options.wa contact_db = args.wa
if options.media is None: if args.media is None:
options.media = "WhatsApp" args.media = "WhatsApp"
if len(args) == 1:
msg_db = args[0]
if os.path.isfile(contact_db): if os.path.isfile(contact_db):
with sqlite3.connect(contact_db) as db: with sqlite3.connect(contact_db) as db:
db.row_factory = sqlite3.Row db.row_factory = sqlite3.Row
contacts(db, data) contacts(db, data)
elif options.iphone: elif args.iphone:
messages = extract_iphone.messages messages = extract_iphone.messages
media = extract_iphone.media media = extract_iphone.media
vcard = extract_iphone.vcard vcard = extract_iphone.vcard
create_html = extract_iphone.create_html create_html = extract_iphone.create_html
if options.backup is not None: if args.backup is not None:
extract_iphone_media.extract_media(options.backup) extract_iphone_media.extract_media(args.backup)
if options.db is None: if args.db is None:
msg_db = "7c7fba66680ef796b916b067077cc246adacf01d" msg_db = "7c7fba66680ef796b916b067077cc246adacf01d"
else: else:
msg_db = options.db msg_db = args.db
if options.wa is None: if args.wa is None:
contact_db = "ContactsV2.sqlite" contact_db = "ContactsV2.sqlite"
else: else:
contact_db = options.wa contact_db = args.wa
if options.media is None: if args.media is None:
options.media = "Message" args.media = "Message"
if len(args) == 1:
msg_db = args[0]
if os.path.isfile(msg_db): if os.path.isfile(msg_db):
with sqlite3.connect(msg_db) as db: with sqlite3.connect(msg_db) as db:
db.row_factory = sqlite3.Row db.row_factory = sqlite3.Row
messages(db, data) messages(db, data)
media(db, data, options.media) media(db, data, args.media)
vcard(db, data) vcard(db, data)
create_html(data, options.output, options.template, options.embedded, options.offline) create_html(data, args.output, args.template, args.embedded, args.offline)
else: else:
print( print(
"The message database does not exist. You may specify the path " "The message database does not exist. You may specify the path "
"to database file with option -d or check your provided path.", "to database file with option -d or check your provided path."
end="\r"
) )
exit(2) exit(2)
if os.path.isdir(options.media): if os.path.isdir(args.media):
if os.path.isdir(f"{options.output}/{options.media}"): if os.path.isdir(f"{args.output}/{args.media}"):
print("Media directory already exists in output directory. Skipping...") print("Media directory already exists in output directory. Skipping...")
else: else:
if not options.move_media: if not args.move_media:
print("Copying media directory...") print("Copying media directory...")
shutil.copytree(options.media, f"{options.output}/WhatsApp") shutil.copytree(args.media, f"{args.output}/WhatsApp")
else: else:
try: try:
shutil.move(options.media, f"{options.output}/") shutil.move(args.media, f"{args.output}/")
except PermissionError: except PermissionError:
print("Cannot remove original WhatsApp directory. " print("Cannot remove original WhatsApp directory. "
"Perhaps the directory is opened?") "Perhaps the directory is opened?")
if options.json: if args.json:
with open("result.json", "w") as f: with open("result.json", "w") as f:
data = json.dumps(data) data = json.dumps(data)
print(f"\nWriting JSON file...({int(len(data)/1024/1024)}MB)") print(f"\nWriting JSON file...({int(len(data)/1024/1024)}MB)")