Prepare for publishing in PyPi

This commit is contained in:
KnugiHK
2021-05-10 15:51:30 +08:00
parent 3ee40ecda4
commit 322281a8ec
7 changed files with 216 additions and 161 deletions

View File

@@ -0,0 +1 @@
__version__ = "0.5"

View File

@@ -7,6 +7,7 @@ import os
import requests import requests
import shutil import shutil
import re import re
import pkgutil
from datetime import datetime from datetime import datetime
from mimetypes import MimeTypes from mimetypes import MimeTypes
@@ -254,7 +255,7 @@ def vcard(db, data):
def create_html(data, output_folder): def create_html(data, output_folder):
templateLoader = jinja2.FileSystemLoader(searchpath="./") templateLoader = jinja2.FileSystemLoader(searchpath=os.path.dirname(__file__))
templateEnv = jinja2.Environment(loader=templateLoader) templateEnv = jinja2.Environment(loader=templateLoader)
templateEnv.globals.update(determine_day=determine_day) templateEnv.globals.update(determine_day=determine_day)
TEMPLATE_FILE = "whatsapp.html" TEMPLATE_FILE = "whatsapp.html"

View File

@@ -6,6 +6,7 @@ import jinja2
import os import os
import requests import requests
import shutil import shutil
import pkgutil
from datetime import datetime from datetime import datetime
from mimetypes import MimeTypes from mimetypes import MimeTypes
@@ -206,12 +207,12 @@ def vcard(db, data):
def create_html(data, output_folder): def create_html(data, output_folder):
templateLoader = jinja2.FileSystemLoader(searchpath="./") templateLoader = jinja2.FileSystemLoader(searchpath=os.path.dirname(__file__))
templateEnv = jinja2.Environment(loader=templateLoader) templateEnv = jinja2.Environment(loader=templateLoader)
templateEnv.globals.update(determine_day=determine_day) templateEnv.globals.update(determine_day=determine_day)
TEMPLATE_FILE = "whatsapp.html" TEMPLATE_FILE = "whatsapp.html"
template = templateEnv.get_template(TEMPLATE_FILE) template = templateEnv.get_template(TEMPLATE_FILE)
total_row_number = len(data) total_row_number = len(data)
print(f"\nCreating HTML...(0/{total_row_number})", end="\r") print(f"\nCreating HTML...(0/{total_row_number})", end="\r")

View File

@@ -73,11 +73,17 @@ def extract_media(base_dir):
if not support_encrypted: if not support_encrypted:
print("You don't have the dependencies to handle encrypted backup.") print("You don't have the dependencies to handle encrypted backup.")
print("Read more about how to deal with encrypted backup:") print("Read more about how to deal with encrypted backup:")
print("https://github.com/KnugiHK/Whatsapp-Chat-Exporter/blob/main/README.md#encrypted-iphone-backup") print("https://github.com/KnugiHK/Whatsapp-Chat-Exporter/blob/main/README.md#usage")
return False return False
password = getpass.getpass("Enter the password:") password = getpass.getpass("Enter the password:")
extract_encrypted(base_dir, password) extract_encrypted(base_dir, password)
else: else:
wts_db = os.path.join(base_dir, "7c/7c7fba66680ef796b916b067077cc246adacf01d")
if not os.path.isfile(wts_db):
print("WhatsApp database not found.")
sys.exit(1)
else:
shutil.copyfile(wts_db, "7c7fba66680ef796b916b067077cc246adacf01d")
with sqlite3.connect(f"{base_dir}/Manifest.db") as manifest: with sqlite3.connect(f"{base_dir}/Manifest.db") as manifest:
c = manifest.cursor() c = manifest.cursor()
c.execute("""SELECT count() c.execute("""SELECT count()

View File

@@ -1,158 +1,158 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Whatsapp - {{ name }}</title> <title>Whatsapp - {{ name }}</title>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<style> <style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@300;400&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@300;400&display=swap');
html { html {
font-family: 'Noto Sans HK', sans-serif; font-family: 'Noto Sans HK', sans-serif;
font-size: 12px; font-size: 12px;
scroll-behavior: smooth; scroll-behavior: smooth;
} }
header { header {
position: fixed; position: fixed;
z-index: 20; z-index: 20;
border-bottom: 2px solid #e3e6e7; border-bottom: 2px solid #e3e6e7;
font-size: 2em; font-size: 2em;
font-weight: bolder; font-weight: bolder;
background-color: white; background-color: white;
padding: 20px 0 20px 0; padding: 20px 0 20px 0;
} }
footer { footer {
border-top: 2px solid #e3e6e7; border-top: 2px solid #e3e6e7;
font-size: 2em; font-size: 2em;
padding: 20px 0 20px 0; padding: 20px 0 20px 0;
} }
article { article {
width:500px; width:500px;
margin:100px auto; margin:100px auto;
z-index:10; z-index:10;
font-size: 15px; font-size: 15px;
word-wrap: break-word; word-wrap: break-word;
} }
img, video { img, video {
max-width:100%; max-width:100%;
} }
a.anchor { a.anchor {
display: block; display: block;
position: relative; position: relative;
top: -100px; top: -100px;
visibility: hidden; visibility: hidden;
} }
div.reply{ div.reply{
font-size: 13px; font-size: 13px;
text-decoration: none; text-decoration: none;
} }
</style> </style>
</head> </head>
<body> <body>
<header class="w3-center w3-top">Chat history with {{ name }}</header> <header class="w3-center w3-top">Chat history with {{ name }}</header>
<article class="w3-container"> <article class="w3-container">
<div class="table" style="width:100%"> <div class="table" style="width:100%">
{% set last = {'last': 946688461.001} %} {% set last = {'last': 946688461.001} %}
{% for msg in msgs -%} {% for msg in msgs -%}
<div class="w3-row" style="padding-bottom: 10px"> <div class="w3-row" style="padding-bottom: 10px">
<a class="anchor" id="{{ msg.key_id }}"></a> <a class="anchor" id="{{ msg.key_id }}"></a>
{% if determine_day(last.last, msg.timestamp) is not none %} {% if determine_day(last.last, msg.timestamp) is not none %}
<div class="w3-center" style="color:#70777c;padding: 10px 0 10px 0;">{{ determine_day(last.last, msg.timestamp) }}</div> <div class="w3-center" style="color:#70777c;padding: 10px 0 10px 0;">{{ determine_day(last.last, msg.timestamp) }}</div>
{% if last.update({'last': msg.timestamp}) %}{% endif %} {% if last.update({'last': msg.timestamp}) %}{% endif %}
{% endif %} {% endif %}
{% if msg.from_me == true %} {% if msg.from_me == true %}
<div class="w3-row"> <div class="w3-row">
<div style="float: left; color:#70777c;">{{ msg.time }}</div> <div style="float: left; color:#70777c;">{{ msg.time }}</div>
<div style="padding-left: 10px; text-align: right; color: #3892da;">You</div> <div style="padding-left: 10px; text-align: right; color: #3892da;">You</div>
</div> </div>
<div class="w3-row"> <div class="w3-row">
<div class="w3-col m10 l10"> <div class="w3-col m10 l10">
<div style="text-align: right;"> <div style="text-align: right;">
{% if msg.reply is not none %} {% if msg.reply is not none %}
<div class="reply"> <div class="reply">
<span style="color: #70777a;">Replying to </span> <span style="color: #70777a;">Replying to </span>
<a href="#{{msg.reply}}" style="color: #168acc;">"{{ msg.quoted_data or 'media' }}"</a> <a href="#{{msg.reply}}" style="color: #168acc;">"{{ msg.quoted_data or 'media' }}"</a>
</div> </div>
{% endif %} {% endif %}
{% if msg.media == false %} {% if msg.media == false %}
{% filter escape %}{{ msg.data or "{This message is not supported yet}" | replace('\n', '<br>') }}{% endfilter %} {% filter escape %}{{ msg.data or "{This message is not supported yet}" | replace('\n', '<br>') }}{% endfilter %}
{% else %} {% else %}
{% if "image/" in msg.mime %} {% if "image/" in msg.mime %}
<a href="{{ msg.data }}"><img src="{{ msg.data }}" /></a> <a href="{{ msg.data }}"><img src="{{ msg.data }}" /></a>
{% elif "audio/" in msg.mime %} {% elif "audio/" in msg.mime %}
<audio controls="controls" autobuffer="autobuffer"> <audio controls="controls" autobuffer="autobuffer">
<source src="{{ msg.data }}" /> <source src="{{ msg.data }}" />
</audio> </audio>
{% elif "video/" in msg.mime %} {% elif "video/" in msg.mime %}
<video controls="controls" autobuffer="autobuffer"> <video controls="controls" autobuffer="autobuffer">
<source src="{{ msg.data }}" /> <source src="{{ msg.data }}" />
</video> </video>
{% elif "/" in msg.mime %} {% elif "/" in msg.mime %}
{The file cannot be displayed here, however it should be located at {{ msg.data }}} {The file cannot be displayed here, however it should be located at {{ msg.data }}}
{% else %} {% else %}
{% filter escape %}{{ msg.data }}{% endfilter %} {% filter escape %}{{ msg.data }}{% endfilter %}
{% endif %} {% endif %}
{% if msg.caption is not none %} {% if msg.caption is not none %}
<br> <br>
{{ msg.caption }} {{ msg.caption }}
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="w3-col m2 l2" style="padding-left: 10px"><img src="{{ my_avatar }}" onerror="this.style.display='none'"></div> <div class="w3-col m2 l2" style="padding-left: 10px"><img src="{{ my_avatar }}" onerror="this.style.display='none'"></div>
</div> </div>
{% else %} {% else %}
<div class="w3-row"> <div class="w3-row">
<div style="padding-right: 10px; float: left; color: #3892da;"> <div style="padding-right: 10px; float: left; color: #3892da;">
{% if msg.sender is not none %} {% if msg.sender is not none %}
{{ msg.sender }} {{ msg.sender }}
{% else %} {% else %}
{{ name }} {{ name }}
{% endif %} {% endif %}
</div> </div>
<div style="text-align: right; color:#70777c;">{{ msg.time }}</div> <div style="text-align: right; color:#70777c;">{{ msg.time }}</div>
</div> </div>
<div class="w3-row"> <div class="w3-row">
<div class="w3-col m2 l2"><img src="{{ their_avatar }}" onerror="this.style.display='none'"></div> <div class="w3-col m2 l2"><img src="{{ their_avatar }}" onerror="this.style.display='none'"></div>
<div class="w3-col m10 l10"> <div class="w3-col m10 l10">
<div style="text-align: left;"> <div style="text-align: left;">
{% if msg.reply is not none %} {% if msg.reply is not none %}
<div class="reply"> <div class="reply">
<span style="color: #70777a;">Replying to </span> <span style="color: #70777a;">Replying to </span>
<a href="#{{msg.reply}}" style="color: #168acc;">"{{ msg.quoted_data or 'media' }}"</a> <a href="#{{msg.reply}}" style="color: #168acc;">"{{ msg.quoted_data or 'media' }}"</a>
</div> </div>
{% endif %} {% endif %}
{% if msg.media == false %} {% if msg.media == false %}
{% filter escape %}{{ msg.data or "{This message is not supported yet}" }}{% endfilter %} {% filter escape %}{{ msg.data or "{This message is not supported yet}" }}{% endfilter %}
{% else %} {% else %}
{% if "image/" in msg.mime %} {% if "image/" in msg.mime %}
<a href="{{ msg.data }}"><img src="{{ msg.data }}" /></a> <a href="{{ msg.data }}"><img src="{{ msg.data }}" /></a>
{% elif "audio/" in msg.mime %} {% elif "audio/" in msg.mime %}
<audio controls="controls" autobuffer="autobuffer"> <audio controls="controls" autobuffer="autobuffer">
<source src="{{ msg.data }}" /> <source src="{{ msg.data }}" />
</audio> </audio>
{% elif "video/" in msg.mime %} {% elif "video/" in msg.mime %}
<video controls="controls" autobuffer="autobuffer"> <video controls="controls" autobuffer="autobuffer">
<source src="{{ msg.data }}" /> <source src="{{ msg.data }}" />
</video> </video>
{% elif "/" in msg.mime %} {% elif "/" in msg.mime %}
{The file cannot be displayed here, however it should be located at {{ msg.data }}} {The file cannot be displayed here, however it should be located at {{ msg.data }}}
{% else %} {% else %}
{% filter escape %}{{ msg.data }}{% endfilter %} {% filter escape %}{{ msg.data }}{% endfilter %}
{% endif %} {% endif %}
{% if msg.caption is not none %} {% if msg.caption is not none %}
<br> <br>
{{ msg.caption }} {{ msg.caption }}
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</article> </article>
<footer class="w3-center"> <footer class="w3-center">
End of history End of history
</footer> </footer>
</body> </body>
</html> </html>

BIN
group.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

46
setup.py Normal file
View File

@@ -0,0 +1,46 @@
import setuptools
from re import search
with open("README.md", "r") as fh:
long_description = fh.read()
with open("Whatsapp_Chat_Exporter/__init__.py", encoding="utf8") as f:
version = search(r'__version__ = "(.*?)"', f.read()).group(1)
setuptools.setup(
name="whatsapp-chat-exporter",
version=version,
author="KnugiHK",
author_email="info@knugi.com",
description="A Whatsapp database parser that will give you the history of your Whatsapp conversations in HTML and JSON.",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/KnugiHK/Whatsapp-Chat-Exporter",
packages=setuptools.find_packages(),
package_data = {
'': ['whatsapp.html']
},
classifiers=[
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.8",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Development Status :: Beta",
"Environment :: Console",
"Intended Audience :: End Users/Desktop"
"Topic :: Communications :: Chat",
"Topic :: Utilities",
"Topic :: Database"
],
python_requires='>=3.7',
install_requires=[
'jinja2'
],
entry_points={
"console_scripts": [
"wtsexporter = Whatsapp_Chat_Exporter.__main__:main"
]
}
)