Comply with PEP8 with some exception

E501 and F401 are not fully enforced
This commit is contained in:
KnugiHK
2021-01-18 15:55:21 +08:00
parent cfb180220c
commit 1d614eafb7
3 changed files with 217 additions and 108 deletions

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python3
import sqlite3 import sqlite3
import sys
import json import json
import jinja2 import jinja2
import os import os
import base64
import requests import requests
import shutil import shutil
import re import re
@@ -21,6 +19,7 @@ def determine_day(last, current):
else: else:
return current return current
def contacts(db, data): def contacts(db, data):
# Get contacts # Get contacts
c = db.cursor() c = db.cursor()
@@ -31,9 +30,10 @@ def contacts(db, data):
c.execute("""SELECT jid, display_name FROM wa_contacts; """) c.execute("""SELECT jid, display_name FROM wa_contacts; """)
row = c.fetchone() row = c.fetchone()
while row is not None: while row is not None:
data[row[0]] = {"name": row[1], "messages":{}} data[row[0]] = {"name": row[1], "messages": {}}
row = c.fetchone() row = c.fetchone()
def messages(db, data): def messages(db, data):
# Get message history # Get message history
c = db.cursor() c = db.cursor()
@@ -42,7 +42,25 @@ def messages(db, data):
print(f"Gathering messages...(0/{total_row_number})", end="\r") print(f"Gathering messages...(0/{total_row_number})", end="\r")
phone_number_re = re.compile(r"[0-9]+@s.whatsapp.net") phone_number_re = re.compile(r"[0-9]+@s.whatsapp.net")
c.execute("""SELECT messages.key_remote_jid, messages._id, messages.key_from_me, messages.timestamp, messages.data, messages.status, messages.edit_version, messages.thumb_image, messages.remote_resource, messages.media_wa_type, messages.latitude, messages.longitude, messages_quotes.key_id as quoted, messages.key_id, messages_quotes.data, messages.media_caption FROM messages LEFT JOIN messages_quotes ON messages.quoted_row_id = messages_quotes._id; """) c.execute("""SELECT messages.key_remote_jid,
messages._id,
messages.key_from_me,
messages.timestamp,
messages.data,
messages.status,
messages.edit_version,
messages.thumb_image,
messages.remote_resource,
messages.media_wa_type,
messages.latitude,
messages.longitude,
messages_quotes.key_id as quoted,
messages.key_id,
messages_quotes.data,
messages.media_caption
FROM messages
LEFT JOIN messages_quotes
ON messages.quoted_row_id = messages_quotes._id;""")
i = 0 i = 0
content = c.fetchone() content = c.fetchone()
while content is not None: while content is not None:
@@ -65,30 +83,33 @@ def messages(db, data):
fallback = None fallback = None
else: else:
fallback = None fallback = None
data[content[0]]["messages"][content[1]]["sender"] = name or fallback data[content[0]]["messages"][content[1]
]["sender"] = name or fallback
else: else:
data[content[0]]["messages"][content[1]]["sender"] = None data[content[0]]["messages"][content[1]]["sender"] = None
if content[12] is not None: if content[12] is not None:
data[content[0]]["messages"][content[1]]["reply"] = content[12] data[content[0]]["messages"][content[1]]["reply"] = content[12]
data[content[0]]["messages"][content[1]]["quoted_data"] = content[14] data[content[0]]["messages"][content[1]
]["quoted_data"] = content[14]
else: else:
data[content[0]]["messages"][content[1]]["reply"] = None data[content[0]]["messages"][content[1]]["reply"] = None
if content[15] is not None: if content[15] is not None:
data[content[0]]["messages"][content[1]]["caption"] = content[15] data[content[0]]["messages"][content[1]]["caption"] = content[15]
else: else:
data[content[0]]["messages"][content[1]]["caption"] = None data[content[0]]["messages"][content[1]]["caption"] = None
if content[5] == 6: if content[5] == 6:
if "-" in content[0]: if "-" in content[0]:
# Is Group # Is Group
if content[4] is not None: if content[4] is not None:
try: try:
int(content[4]) int(content[4])
except: except ValueError:
data[content[0]]["messages"][content[1]]["data"] = "{The group name changed to "f"{content[4]}"" }" msg = "{The group name changed to "f"{content[4]}"" }"
data[content[0]]["messages"][content[1]]["data"] = msg
else: else:
del data[content[0]]["messages"][content[1]] del data[content[0]]["messages"][content[1]]
else: else:
@@ -96,7 +117,8 @@ def messages(db, data):
if thumb_image is not None: if thumb_image is not None:
if b"\x00\x00\x01\x74\x00\x1A" in thumb_image: if b"\x00\x00\x01\x74\x00\x1A" in thumb_image:
# Add user # Add user
added = phone_number_re.search(thumb_image.decode("unicode_escape"))[0] added = phone_number_re.search(
thumb_image.decode("unicode_escape"))[0]
if added in data: if added in data:
name_right = data[added]["name"] name_right = data[added]["name"]
else: else:
@@ -106,14 +128,15 @@ def messages(db, data):
name_left = data[content[8]]["name"] name_left = data[content[8]]["name"]
else: else:
name_left = content[8].split('@')[0] name_left = content[8].split('@')[0]
data[content[0]]["messages"][content[1]]["data"] = "{"f"{name_left}"f" added {name_right or 'You'}""}" msg = "{"f"{name_left}"f" added {name_right or 'You'}""}"
else: else:
data[content[0]]["messages"][content[1]]["data"] = "{"f"Added {name_right or 'You'}""}" msg = "{"f"Added {name_right or 'You'}""}"
if b"\xac\xed\x00\x05\x74\x00" in thumb_image: elif b"\xac\xed\x00\x05\x74\x00" in thumb_image:
# Changed number # Changed number
original = content[8].split('@')[0] original = content[8].split('@')[0]
changed = thumb_image[7:].decode().split('@')[0] changed = thumb_image[7:].decode().split('@')[0]
data[content[0]]["messages"][content[1]]["data"] = "{"f"{original} changed to {changed}""}" msg = "{"f"{original} changed to {changed}""}"
data[content[0]]["messages"][content[1]]["data"] = msg
else: else:
if content[4] is None: if content[4] is None:
del data[content[0]]["messages"][content[1]] del data[content[0]]["messages"][content[1]]
@@ -121,30 +144,34 @@ def messages(db, data):
# Private chat # Private chat
if content[4] is None and content[7] is None: if content[4] is None and content[7] is None:
del data[content[0]]["messages"][content[1]] del data[content[0]]["messages"][content[1]]
else: else:
if content[2] == 1: if content[2] == 1:
if content[5] == 5 and content[6] == 7: if content[5] == 5 and content[6] == 7:
data[content[0]]["messages"][content[1]]["data"] = "{Message deleted}" msg = "{Message deleted}"
else: else:
if content[9] == "5": if content[9] == "5":
data[content[0]]["messages"][content[1]]["data"] = "{ Location shared: "f"{content[10], content[11]}"" }" msg = "{ Location shared: "f"{content[10], content[11]}"" }"
else: else:
data[content[0]]["messages"][content[1]]["data"] = content[4] msg = content[4]
else: else:
if content[5] == 0 and content[6] == 7: if content[5] == 0 and content[6] == 7:
data[content[0]]["messages"][content[1]]["data"] = "{Message deleted}" msg = "{Message deleted}"
else: else:
if content[9] == "5": if content[9] == "5":
data[content[0]]["messages"][content[1]]["data"] = "{ Location shared: "f"{content[10], content[11]}"" }" msg = "{ Location shared: "f"{content[10], content[11]}"" }"
else: else:
data[content[0]]["messages"][content[1]]["data"] = content[4] msg = content[4]
data[content[0]]["messages"][content[1]]["data"] = msg
i += 1 i += 1
if i % 1000 == 0: if i % 1000 == 0:
print(f"Gathering messages...({i}/{total_row_number})", end="\r") print(f"Gathering messages...({i}/{total_row_number})", end="\r")
content = c.fetchone() content = c.fetchone()
print(f"Gathering messages...({total_row_number}/{total_row_number})", end="\r") print(
f"Gathering messages...({total_row_number}/{total_row_number})", end="\r")
def media(db, data, media_folder): def media(db, data, media_folder):
# Get media # Get media
@@ -153,7 +180,16 @@ def media(db, data, media_folder):
total_row_number = c.fetchone()[0] total_row_number = c.fetchone()[0]
print(f"\nGathering media...(0/{total_row_number})", end="\r") print(f"\nGathering media...(0/{total_row_number})", end="\r")
i = 0 i = 0
c.execute("""SELECT messages.key_remote_jid, message_row_id, file_path, message_url, mime_type, media_key FROM message_media INNER JOIN messages ON message_media.message_row_id = messages._id ORDER BY messages.key_remote_jid ASC""") c.execute("""SELECT messages.key_remote_jid,
message_row_id,
file_path,
message_url,
mime_type,
media_key
FROM message_media
INNER JOIN messages
ON message_media.message_row_id = messages._id
ORDER BY messages.key_remote_jid ASC""")
content = c.fetchone() content = c.fetchone()
mime = MimeTypes() mime = MimeTypes()
while content is not None: while content is not None:
@@ -171,26 +207,36 @@ def media(db, data, media_folder):
data[content[0]]["messages"][content[1]]["mime"] = content[4] data[content[0]]["messages"][content[1]]["mime"] = content[4]
else: else:
# if "https://mmg" in content[4]: # if "https://mmg" in content[4]:
# try: # try:
# r = requests.get(content[3]) # r = requests.get(content[3])
# if r.status_code != 200: # if r.status_code != 200:
# raise RuntimeError() # raise RuntimeError()
# except: # except:
# data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}" # data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}"
# data[content[0]]["messages"][content[1]]["media"] = True # data[content[0]]["messages"][content[1]]["media"] = True
# data[content[0]]["messages"][content[1]]["mime"] = "media" # data[content[0]]["messages"][content[1]]["mime"] = "media"
# else: # else:
data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}" data[content[0]]["messages"][content[1]
]["data"] = "{The media is missing}"
data[content[0]]["messages"][content[1]]["mime"] = "media" data[content[0]]["messages"][content[1]]["mime"] = "media"
i += 1 i += 1
if i % 100 == 0: if i % 100 == 0:
print(f"Gathering media...({i}/{total_row_number})", end="\r") print(f"Gathering media...({i}/{total_row_number})", end="\r")
content = c.fetchone() content = c.fetchone()
print(f"Gathering media...({total_row_number}/{total_row_number})", end="\r") print(
f"Gathering media...({total_row_number}/{total_row_number})", end="\r")
def vcard(db, data): def vcard(db, data):
c = db.cursor() c = db.cursor()
c.execute("""SELECT message_row_id, messages.key_remote_jid, vcard, messages.media_name FROM messages_vcards INNER JOIN messages ON messages_vcards.message_row_id = messages._id ORDER BY messages.key_remote_jid ASC""") c.execute("""SELECT message_row_id,
messages.key_remote_jid,
vcard,
messages.media_name
FROM messages_vcards
INNER JOIN messages
ON messages_vcards.message_row_id = messages._id
ORDER BY messages.key_remote_jid ASC;""")
rows = c.fetchall() rows = c.fetchall()
total_row_number = len(rows) total_row_number = len(rows)
print(f"\nGathering vCards...(0/{total_row_number})", end="\r") print(f"\nGathering vCards...(0/{total_row_number})", end="\r")
@@ -203,10 +249,13 @@ def vcard(db, data):
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
with open(file_path, "w", encoding="utf-8") as f: with open(file_path, "w", encoding="utf-8") as f:
f.write(row[2]) f.write(row[2])
data[row[1]]["messages"][row[0]]["data"] = row[3] + "{ The vCard file cannot be displayed here, however it should be located at " + file_path + "}" data[row[1]]["messages"][row[0]]["data"] = row[3] + \
"{ The vCard file cannot be displayed here, however it " \
"should be located at " + file_path + "}"
data[row[1]]["messages"][row[0]]["mime"] = "x-vcard" data[row[1]]["messages"][row[0]]["mime"] = "x-vcard"
print(f"Gathering vCards...({index + 1}/{total_row_number})", end="\r") print(f"Gathering vCards...({index + 1}/{total_row_number})", end="\r")
def create_html(data, output_folder): def create_html(data, output_folder):
templateLoader = jinja2.FileSystemLoader(searchpath="./") templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader) templateEnv = jinja2.Environment(loader=templateLoader)
@@ -224,11 +273,11 @@ def create_html(data, output_folder):
if len(data[i]["messages"]) == 0: if len(data[i]["messages"]) == 0:
continue continue
phone_number = i.split('@')[0] phone_number = i.split('@')[0]
if "-"in i: if "-" in i:
file_name = "" file_name = ""
else: else:
file_name = phone_number file_name = phone_number
if data[i]["name"] is not None: if data[i]["name"] is not None:
if file_name != "": if file_name != "":
file_name += "-" file_name += "-"
@@ -237,12 +286,14 @@ def create_html(data, output_folder):
else: else:
name = phone_number name = phone_number
safe_file_name = '' safe_file_name = ''
safe_file_name = "".join(x for x in file_name if x.isalnum() or x in "- ") safe_file_name = "".join(
x for x in file_name if x.isalnum() or x in "- ")
with open(f"{output_folder}/{safe_file_name}.html", "w", encoding="utf-8") as f: with open(f"{output_folder}/{safe_file_name}.html", "w", encoding="utf-8") as f:
f.write(template.render(name=name, msgs=data[i]["messages"].values(), my_avatar=None, their_avatar=f"WhatsApp/Avatars/{i}.j")) f.write(template.render(name=name, msgs=data[i]["messages"].values(
), my_avatar=None, their_avatar=f"WhatsApp/Avatars/{i}.j"))
if current % 10 == 0: if current % 10 == 0:
print(f"Creating HTML...({current}/{total_row_number})", end="\r") print(f"Creating HTML...({current}/{total_row_number})", end="\r")
print(f"Creating HTML...({total_row_number}/{total_row_number})", end="\r") print(f"Creating HTML...({total_row_number}/{total_row_number})", end="\r")
@@ -267,7 +318,7 @@ if __name__ == "__main__":
# "--template", # "--template",
# dest="html", # dest="html",
# default="wa.db", # default="wa.db",
# help="Path to HTML template") # help="Path to HTML template")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
msg_db = "msgstore.db" msg_db = "msgstore.db"
output_folder = "temp" output_folder = "temp"
@@ -279,7 +330,7 @@ if __name__ == "__main__":
elif len(args) == 2: elif len(args) == 2:
msg_db = args[0] msg_db = args[0]
output_folder = args[1] output_folder = args[1]
data = {} data = {}
if os.path.isfile(contact_db): if os.path.isfile(contact_db):

View File

@@ -1,17 +1,16 @@
#!/usr/bin/python3 #!/usr/bin/python3
import sqlite3 import sqlite3
import sys
import json import json
import jinja2 import jinja2
import os import os
import base64
import requests import requests
import shutil import shutil
from datetime import datetime from datetime import datetime
from mimetypes import MimeTypes from mimetypes import MimeTypes
APPLE_TIME = datetime.timestamp(datetime(2001,1,1)) APPLE_TIME = datetime.timestamp(datetime(2001, 1, 1))
def determine_day(last, current): def determine_day(last, current):
last = datetime.fromtimestamp(last).date() last = datetime.fromtimestamp(last).date()
@@ -21,6 +20,7 @@ def determine_day(last, current):
else: else:
return current return current
def messages(db, data): def messages(db, data):
c = db.cursor() c = db.cursor()
# Get contacts # Get contacts
@@ -31,7 +31,7 @@ def messages(db, data):
c.execute("""SELECT ZCONTACTJID, ZPARTNERNAME FROM ZWACHATSESSION; """) c.execute("""SELECT ZCONTACTJID, ZPARTNERNAME FROM ZWACHATSESSION; """)
row = c.fetchone() row = c.fetchone()
while row is not None: while row is not None:
data[row[0]] = {"name": row[1], "messages":{}} data[row[0]] = {"name": row[1], "messages": {}}
row = c.fetchone() row = c.fetchone()
# Get message history # Get message history
@@ -39,7 +39,16 @@ def messages(db, data):
total_row_number = c.fetchone()[0] total_row_number = c.fetchone()[0]
print(f"Gathering messages...(0/{total_row_number})", end="\r") print(f"Gathering messages...(0/{total_row_number})", end="\r")
c.execute("""SELECT COALESCE(ZFROMJID, ZTOJID), ZWAMESSAGE.Z_PK, ZISFROMME, ZMESSAGEDATE, ZTEXT, ZMESSAGETYPE, ZWAGROUPMEMBER.ZMEMBERJID FROM main.ZWAMESSAGE LEFT JOIN main.ZWAGROUPMEMBER ON main.ZWAMESSAGE.ZGROUPMEMBER = main.ZWAGROUPMEMBER.Z_PK;""") c.execute("""SELECT COALESCE(ZFROMJID, ZTOJID),
ZWAMESSAGE.Z_PK,
ZISFROMME,
ZMESSAGEDATE,
ZTEXT,
ZMESSAGETYPE,
ZWAGROUPMEMBER.ZMEMBERJID
FROM main.ZWAMESSAGE
LEFT JOIN main.ZWAGROUPMEMBER
ON main.ZWAMESSAGE.ZGROUPMEMBER = main.ZWAGROUPMEMBER.Z_PK;""")
i = 0 i = 0
content = c.fetchone() content = c.fetchone()
while content is not None: while content is not None:
@@ -65,7 +74,8 @@ def messages(db, data):
fallback = None fallback = None
else: else:
fallback = None fallback = None
data[content[0]]["messages"][content[1]]["sender"] = name or fallback data[content[0]]["messages"][content[1]
]["sender"] = name or fallback
else: else:
data[content[0]]["messages"][content[1]]["sender"] = None data[content[0]]["messages"][content[1]]["sender"] = None
if content[5] == 6: if content[5] == 6:
@@ -76,8 +86,9 @@ def messages(db, data):
# Chnaged name # Chnaged name
try: try:
int(content[4]) int(content[4])
except: except ValueError:
data[content[0]]["messages"][content[1]]["data"] = "{The group name changed to "f"{content[4]}"" }" msg = "{The group name changed to "f"{content[4]}"" }"
data[content[0]]["messages"][content[1]]["data"] = msg
else: else:
del data[content[0]]["messages"][content[1]] del data[content[0]]["messages"][content[1]]
else: else:
@@ -88,21 +99,23 @@ def messages(db, data):
# real message # real message
if content[2] == 1: if content[2] == 1:
if content[5] == 14: if content[5] == 14:
data[content[0]]["messages"][content[1]]["data"] = "{Message deleted}" msg = "{Message deleted}"
else: else:
data[content[0]]["messages"][content[1]]["data"] = content[4] msg = content[4]
else: else:
if content[5] == 14: if content[5] == 14:
data[content[0]]["messages"][content[1]]["data"] = "{Message deleted}" msg = "{Message deleted}"
else: else:
data[content[0]]["messages"][content[1]]["data"] = content[4] msg = content[4]
data[content[0]]["messages"][content[1]]["data"] = msg
i += 1 i += 1
if i % 1000 == 0: if i % 1000 == 0:
print(f"Gathering messages...({i}/{total_row_number})", end="\r") print(f"Gathering messages...({i}/{total_row_number})", end="\r")
content = c.fetchone() content = c.fetchone()
print(f"Gathering messages...({total_row_number}/{total_row_number})", end="\r") print(
f"Gathering messages...({total_row_number}/{total_row_number})", end="\r")
def media(db, data, media_folder): def media(db, data, media_folder):
c = db.cursor() c = db.cursor()
# Get media # Get media
@@ -110,13 +123,24 @@ def media(db, data, media_folder):
total_row_number = c.fetchone()[0] total_row_number = c.fetchone()[0]
print(f"\nGathering media...(0/{total_row_number})", end="\r") print(f"\nGathering media...(0/{total_row_number})", end="\r")
i = 0 i = 0
c.execute("""SELECT COALESCE(ZWAMESSAGE.ZFROMJID, ZWAMESSAGE.ZTOJID) as _id, ZMESSAGE, ZMEDIALOCALPATH, ZMEDIAURL, ZVCARDSTRING, ZMEDIAKEY, ZTITLE FROM ZWAMEDIAITEM INNER JOIN ZWAMESSAGE ON ZWAMEDIAITEM.ZMESSAGE = ZWAMESSAGE.Z_PK WHERE ZMEDIALOCALPATH IS NOT NULL ORDER BY _id ASC""") c.execute("""SELECT COALESCE(ZWAMESSAGE.ZFROMJID, ZWAMESSAGE.ZTOJID) as _id,
ZMESSAGE,
ZMEDIALOCALPATH,
ZMEDIAURL,
ZVCARDSTRING,
ZMEDIAKEY,
ZTITLE
FROM ZWAMEDIAITEM
INNER JOIN ZWAMESSAGE
ON ZWAMEDIAITEM.ZMESSAGE = ZWAMESSAGE.Z_PK
WHERE ZMEDIALOCALPATH IS NOT NULL
ORDER BY _id ASC""")
content = c.fetchone() content = c.fetchone()
mime = MimeTypes() mime = MimeTypes()
while content is not None: while content is not None:
file_path = f"Message/{content[2]}" file_path = f"Message/{content[2]}"
data[content[0]]["messages"][content[1]]["media"] = True data[content[0]]["messages"][content[1]]["media"] = True
if os.path.isfile(file_path): if os.path.isfile(file_path):
data[content[0]]["messages"][content[1]]["data"] = file_path data[content[0]]["messages"][content[1]]["data"] = file_path
if content[4] is None: if content[4] is None:
@@ -129,15 +153,16 @@ def media(db, data, media_folder):
data[content[0]]["messages"][content[1]]["mime"] = content[4] data[content[0]]["messages"][content[1]]["mime"] = content[4]
else: else:
# if "https://mmg" in content[4]: # if "https://mmg" in content[4]:
# try: # try:
# r = requests.get(content[3]) # r = requests.get(content[3])
# if r.status_code != 200: # if r.status_code != 200:
# raise RuntimeError() # raise RuntimeError()
# except: # except:
# data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}" # data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}"
# data[content[0]]["messages"][content[1]]["mime"] = "media" # data[content[0]]["messages"][content[1]]["mime"] = "media"
# else: # else:
data[content[0]]["messages"][content[1]]["data"] = "{The media is missing}" data[content[0]]["messages"][content[1]
]["data"] = "{The media is missing}"
data[content[0]]["messages"][content[1]]["mime"] = "media" data[content[0]]["messages"][content[1]]["mime"] = "media"
if content[6] is not None: if content[6] is not None:
data[content[0]]["messages"][content[1]]["caption"] = content[6] data[content[0]]["messages"][content[1]]["caption"] = content[6]
@@ -145,11 +170,23 @@ def media(db, data, media_folder):
if i % 100 == 0: if i % 100 == 0:
print(f"Gathering media...({i}/{total_row_number})", end="\r") print(f"Gathering media...({i}/{total_row_number})", end="\r")
content = c.fetchone() content = c.fetchone()
print(f"Gathering media...({total_row_number}/{total_row_number})", end="\r") print(
f"Gathering media...({total_row_number}/{total_row_number})", end="\r")
def vcard(db, data): def vcard(db, data):
c = db.cursor() c = db.cursor()
c.execute("""SELECT DISTINCT ZWAVCARDMENTION.ZMEDIAITEM, ZWAMEDIAITEM.ZMESSAGE, COALESCE(ZWAMESSAGE.ZFROMJID, ZWAMESSAGE.ZTOJID) as _id, ZVCARDNAME, ZVCARDSTRING FROM ZWAVCARDMENTION INNER JOIN ZWAMEDIAITEM ON ZWAVCARDMENTION.ZMEDIAITEM = ZWAMEDIAITEM.Z_PK INNER JOIN ZWAMESSAGE ON ZWAMEDIAITEM.ZMESSAGE = ZWAMESSAGE.Z_PK""") c.execute("""SELECT DISTINCT ZWAVCARDMENTION.ZMEDIAITEM,
ZWAMEDIAITEM.ZMESSAGE,
COALESCE(ZWAMESSAGE.ZFROMJID,
ZWAMESSAGE.ZTOJID) as _id,
ZVCARDNAME,
ZVCARDSTRING
FROM ZWAVCARDMENTION
INNER JOIN ZWAMEDIAITEM
ON ZWAVCARDMENTION.ZMEDIAITEM = ZWAMEDIAITEM.Z_PK
INNER JOIN ZWAMESSAGE
ON ZWAMEDIAITEM.ZMESSAGE = ZWAMESSAGE.Z_PK""")
rows = c.fetchall() rows = c.fetchall()
total_row_number = len(rows) total_row_number = len(rows)
print(f"\nGathering vCards...(0/{total_row_number})", end="\r") print(f"\nGathering vCards...(0/{total_row_number})", end="\r")
@@ -162,11 +199,14 @@ def vcard(db, data):
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
with open(file_path, "w", encoding="utf-8") as f: with open(file_path, "w", encoding="utf-8") as f:
f.write(row[4]) f.write(row[4])
data[row[2]]["messages"][row[1]]["data"] = row[3] + "{ The vCard file cannot be displayed here, however it should be located at " + file_path + "}" data[row[2]]["messages"][row[1]]["data"] = row[3] + \
"{ The vCard file cannot be displayed here, however it " \
"should be located at " + file_path + "}"
data[row[2]]["messages"][row[1]]["mime"] = "x-vcard" data[row[2]]["messages"][row[1]]["mime"] = "x-vcard"
data[row[2]]["messages"][row[1]]["media"] = True data[row[2]]["messages"][row[1]]["media"] = True
print(f"Gathering vCards...({index + 1}/{total_row_number})", end="\r") print(f"Gathering vCards...({index + 1}/{total_row_number})", end="\r")
def create_html(data, output_folder): def create_html(data, output_folder):
templateLoader = jinja2.FileSystemLoader(searchpath="./") templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader) templateEnv = jinja2.Environment(loader=templateLoader)
@@ -184,11 +224,11 @@ def create_html(data, output_folder):
if len(data[i]["messages"]) == 0: if len(data[i]["messages"]) == 0:
continue continue
phone_number = i.split('@')[0] phone_number = i.split('@')[0]
if "-"in i: if "-" in i:
file_name = "" file_name = ""
else: else:
file_name = phone_number file_name = phone_number
if data[i]["name"] is not None: if data[i]["name"] is not None:
if file_name != "": if file_name != "":
file_name += "-" file_name += "-"
@@ -196,16 +236,18 @@ def create_html(data, output_folder):
name = data[i]["name"] name = data[i]["name"]
else: else:
name = phone_number name = phone_number
safe_file_name = '' safe_file_name = ''
safe_file_name = "".join(x for x in file_name if x.isalnum() or x in "- ") safe_file_name = "".join(x for x in file_name if x.isalnum() or x in "- ")
with open(f"{output_folder}/{safe_file_name}.html", "w", encoding="utf-8") as f: with open(f"{output_folder}/{safe_file_name}.html", "w", encoding="utf-8") as f:
f.write(template.render(name=name, msgs=data[i]["messages"].values(), my_avatar=None, their_avatar=f"WhatsApp/Avatars/{i}.j")) f.write(template.render(name=name, msgs=data[i]["messages"].values(
), my_avatar=None, their_avatar=f"WhatsApp/Avatars/{i}.j"))
if current % 10 == 0: if current % 10 == 0:
print(f"Creating HTML...({current}/{total_row_number})", end="\r") print(f"Creating HTML...({current}/{total_row_number})", end="\r")
print(f"Creating HTML...({total_row_number}/{total_row_number})", end="\r") print(f"Creating HTML...({total_row_number}/{total_row_number})", end="\r")
if __name__ == "__main__": if __name__ == "__main__":
from optparse import OptionParser from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
@@ -227,7 +269,7 @@ if __name__ == "__main__":
# "--template", # "--template",
# dest="html", # dest="html",
# default="wa.db", # default="wa.db",
# help="Path to HTML template") # help="Path to HTML template")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
msg_db = "7c7fba66680ef796b916b067077cc246adacf01d" msg_db = "7c7fba66680ef796b916b067077cc246adacf01d"
output_folder = "temp" output_folder = "temp"
@@ -239,7 +281,7 @@ if __name__ == "__main__":
elif len(args) == 2: elif len(args) == 2:
msg_db = args[0] msg_db = args[0]
output_folder = args[1] output_folder = args[1]
data = {} data = {}
if os.path.isfile(msg_db): if os.path.isfile(msg_db):

View File

@@ -4,30 +4,46 @@ import shutil
import sqlite3 import sqlite3
import os import os
manifest = sqlite3.connect(f"{sys.argv[2]}/Manifest.db")
c = manifest.cursor() def extract_media(base_dir):
c.execute("""SELECT count() FROM Files WHERE relativePath LIKE 'Message/Media/%'""") with sqlite3.connect(f"{base_dir}/Manifest.db") as manifest:
total_row_number = c.fetchone()[0] c = manifest.cursor()
print(f"Gathering media...(0/{total_row_number})", end="\r") c.execute("""SELECT count()
c.execute("""SELECT fileID, relativePath, flags FROM Files WHERE relativePath LIKE 'Message/Media/%'""") FROM Files
row = c.fetchone() WHERE relativePath
if not os.path.isdir("Message"): LIKE 'Message/Media/%'""")
os.mkdir("Message") total_row_number = c.fetchone()[0]
if not os.path.isdir("Message/Media"): print(f"Gathering media...(0/{total_row_number})", end="\r")
os.mkdir("Message/Media") c.execute("""SELECT fileID,
i = 0 relativePath,
while row is not None: flags
destination = row[1] FROM Files
hashes = row[0] WHERE relativePath
folder = hashes[:2] LIKE 'Message/Media/%'""")
flags = row[2] row = c.fetchone()
if flags == 2: if not os.path.isdir("Message"):
os.mkdir(destination) os.mkdir("Message")
elif flags == 1: if not os.path.isdir("Message/Media"):
shutil.copyfile(f"{sys.argv[2]}/{folder}/{hashes}", destination) os.mkdir("Message/Media")
i += 1 i = 0
if i % 100 == 0: while row is not None:
print(f"Gathering media...({i}/{total_row_number})", end="\r") destination = row[1]
row = c.fetchone() hashes = row[0]
print(f"Gathering media...({total_row_number}/{total_row_number})", end="\r") folder = hashes[:2]
manifest.close() flags = row[2]
if flags == 2:
os.mkdir(destination)
elif flags == 1:
shutil.copyfile(f"{base_dir}/{folder}/{hashes}", destination)
i += 1
if i % 100 == 0:
print(f"Gathering media...({i}/{total_row_number})", end="\r")
row = c.fetchone()
print(f"Gathering media...({total_row_number}/{total_row_number})", end="\r")
if __name__ == "__main__":
from optparse import OptionParser
parser = OptionParser()
(_, args) = parser.parse_args()
base_dir = args[0]