Whatsapp chat book
Presenting by Madhan Kumar Selvaraj
More than 2 billion people are using the Whats-app application as per the report. It replaced all of our chatting applications and most of our formal, as well as informal chats, are happening through the Whats-app. Those chats are between our family, friends, spouse, our loved ones. I got an idea of printing the chat in the form of a book or hard copy kind of thing to make our bond as a lifetime memory.
Real-world issue
- One of the easiest ways to convert the chat into PDF format is by taking the long screenshot of our Whats-app chat in the application and converting it into PDF. The problem is that Whats-app deletes messages frequently in the application and we can't able to change the font type, size, color. Quality of taking the long screenshot is not that efficient to convert into the printable format and most of the applications are proprietary.
- Some of the websites like Zapptales are providing options to convert the exported Whats-app chat into a printable format. The problem is that it is a proprietary one and we need to share our private chat with them.
The workflow of the project
- Export the Whatsapp chat from the Whatsapp mobile application
- Do the text processing for the exported chat
- Create a landing page for the website
- Create a conversation page to load the chat to display the conversation on the page
- Option to convert the HTML page content to PDF
- Create a CSV file to create statistics graph by using Plotly
Technologies used here
Whatsapp book
- View chat conversation
- Option to download the chat
- Statistics based on chat activity
Text processing
date_pattern = '\d\d\/\d\d\/\d\d\d\d'
time_pattern = '\d\d\:\d\d'
name_pattern = '- \w.*\S\)?: '
name_addon_pattern = "\w.*\w"
chat_pattern = ': .*'
attachment_pattern = "IMG\S*"
group_name_pattern = "with .*\.txt"
View chat conversation
import io
import re
import csv
import configuration
def date_time(string, pattern):
try:
return re.findall(pattern, string)[0]
except:
return ""
def chat_generator(WAfile, filename):
chat_list = []
unique_names = set()
name_dict = {}
check_date = None
file = WAfile.decode("utf-8")
text_convert = io.StringIO(file)
content = text_convert.readlines()
if filename == "statistics":
with open(configuration.csv_file_path, 'w+', encoding='utf-8', newline='') as file:
writer = csv.writer(file)
writer.writerow(["Name", "Date", "Time", "Chat"])
for each_chat in content:
try:
name_result = re.findall(configuration.name_addon_pattern, re.findall(configuration.name_pattern, each_chat)[0])[0]
unique_names.add(name_result)
except:
pass
len_unique_names = len(unique_names)
for index, name in enumerate(unique_names):
name_dict[name] = index
for each_chat in content:
date_result = date_time(each_chat, configuration.date_pattern)
time_result = date_time(each_chat, configuration.time_pattern)
try:
chat_result = re.findall(configuration.chat_pattern, each_chat)[0].replace(": ", "")
except:
chat_result = ""
try:
name_result = re.findall(configuration.name_addon_pattern, re.findall(configuration.name_pattern, each_chat)[0])[0]
except:
name_result = ""
name_result_copy = name_result
try:
attachment_result = re.findall(configuration.attachment_pattern, each_chat)[0]
chat_result = " "
except:
attachment_result = ""
if(filename != "statistics"):
if (date_result != check_date):
check_date = date_result
else:
date_result = ""
try:
name_result = name_dict[name_result]
except:
name_result = ""
if (chat_result != "") & (filename != "statistics") :
list_data = [date_result, time_result, name_result, chat_result, attachment_result, name_result_copy]
chat_list.append(list_data)
elif(chat_result != "") & (filename == "statistics"):
list_data = [name_result_copy, date_result, time_result, chat_result]
with open(configuration.csv_file_path, 'a+', encoding='utf-8', newline='') as file:
writer = csv.writer(file)
writer.writerow(list_data)
date_result = time_result = name_result = chat_result = attachment_result = chat_name_id = chat_name = ""
if filename != "statistics":
if len_unique_names==2:
for chat_name in unique_names:
chat_name_id = name_dict[chat_name]
else:
chat_name = re.findall(configuration.group_name_pattern, filename)[0].replace("with ","").replace(".txt","")
if filename != "statistics":
return chat_name, chat_name_id, chat_list, len_unique_names
elif filename == "statistics":
return "success"
One-to-One chat
Group chat
import flask
from flask import Flask, render_template, request, url_for
from flask_weasyprint import HTML, render_pdf
import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import plotly.express as px
import configuration
import main
server = Flask(__name__)
server.debug = True
@server.route('/', methods=['GET', 'POST'])
def landing_page():
if request.method == 'POST':
if ('file' in request.files):
file = request.files['file']
filename = request.files['file'].filename
choice = request.form["optradio"]
if choice=="view":
name, chat_name_id, chat_data, no_of_users = main.chat_generator(file.read(), filename)
return render_template('chat_box.html', chat_name_id = chat_name_id, no_of_users = no_of_users, name = name, chat = chat_data, color_code = configuration.color_code_dict)
elif choice == "download":
name, chat_name_id, chat_data, no_of_users = main.chat_generator(file.read(), filename)
html = render_template('chat_box.html', chat_name_id = chat_name_id, no_of_users = no_of_users, name = name, chat = chat_data, color_code = configuration.color_code_dict)
return render_pdf(HTML(string=html))
elif choice == "statistics":
print(main.chat_generator(file.read(), choice))
return flask.redirect('/statistics')
else:
return render_template('landing_page.html')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
app = dash.Dash(
__name__,
server=server, external_stylesheets=external_stylesheets,
routes_pathname_prefix='/statistics/'
)
wa_df = pd.read_csv(configuration.csv_file_path)
wa_df['Time'] = pd.to_datetime(wa_df['Time'], format='%H:%M')
#wa_df['Date'] = pd.to_datetime(wa_df['Date'], format='%d/%m/%Y')
date_df = pd.DataFrame(wa_df["Date"].value_counts())
date_df = date_df.rename(columns={"Date":"Number of chats"})
date_df['Date']= date_df.index
name_df = pd.DataFrame(wa_df["Name"].value_counts())
name_df = pd.DataFrame(wa_df["Name"].value_counts())
name_df = name_df.rename(columns={"Name":"Number of chats"})
name_df['Name']= name_df.index
fig = px.bar(date_df, x="Date", y="Number of chats", text='Number of chats', title='Number of chats based on date')
fig1 = px.pie(name_df, names='Name', values='Number of chats', title='Number of chats by person')
fig2 = px.line(wa_df, x='Date', y='Time', title='Chat timings')
fig.update_layout(
plot_bgcolor=colors['background'],
paper_bgcolor=colors['background'],
font_color=colors['text']
)
fig1.update_layout(
plot_bgcolor=colors['background'],
paper_bgcolor=colors['background'],
font_color=colors['text']
)
fig2.update_layout(
plot_bgcolor=colors['background'],
paper_bgcolor=colors['background'],
font_color=colors['text']
)
app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
html.H1(
children='Whatsapp chat statistics',
style={
'textAlign': 'center',
'color': colors['text']
}
),
dcc.Graph(
id='Whatsapp',
figure=fig
),
dcc.Graph(
id='Whatsapp1',
figure=fig1
),
dcc.Graph(
id='Whatsapp2',
figure=fig2
)
])
if __name__ == '__main__':
server.run(debug=True)
Option to download the chat
Statistics based on chat activity
Heroku deployment
I deploy this application in the Heroku cloud without the download chat feature. The reason is that we can't install weasyprint and its dependency on the Heroku. Play with the below live application.
Limitations of this application
- The Dash framework is under the developing stage. So there is no option to load the new data for the statistics. It'll use the same CSV file every time after deployment and it shows statistics for the same chat. We can also use Bokeh instead of the Dash framework.
- You need to keep the attachment under the static/attachments folder to view the attachments. Or else you can update the script by getting multiple documents in the form input.
Ready-made code
Finally, we created our own Whatsapp book application. Still, there is a lot of improvement needed in this application. Make this project as a reference and update it as per your taste. Happy coding!
P.S - Whatever the things that we are learning today, won't get waste for any cost. Load your brain every day and fire your skills during the right moment.
I was surfing net and fortunately came across this site and found very interesting stuff here. Its really fun to read. ai chatbot online
ReplyDelete