diff --git a/Whatsapp_Chat_Exporter/__main__.py b/Whatsapp_Chat_Exporter/__main__.py index 07a341b..c8be561 100644 --- a/Whatsapp_Chat_Exporter/__main__.py +++ b/Whatsapp_Chat_Exporter/__main__.py @@ -25,7 +25,10 @@ from Whatsapp_Chat_Exporter.vcards_contacts import ContactsFromVCards logger = logging.getLogger(__name__) -__version__ = importlib.metadata.version("whatsapp_chat_exporter") +try: + __version__ = importlib.metadata.version("whatsapp_chat_exporter") +except importlib.metadata.PackageNotFoundError: + __version__ = "0.13.0rc2" WTSEXPORTER_BANNER = f"""======================================================================================================== ██╗ ██╗██╗ ██╗ █████╗ ████████╗███████╗ █████╗ ██████╗ ██████╗ ██║ ██║██║ ██║██╔══██╗╚══██╔══╝██╔════╝██╔══██╗██╔══██╗██╔══██╗ diff --git a/Whatsapp_Chat_Exporter/android_handler.py b/Whatsapp_Chat_Exporter/android_handler.py index 274661b..1b11e78 100644 --- a/Whatsapp_Chat_Exporter/android_handler.py +++ b/Whatsapp_Chat_Exporter/android_handler.py @@ -98,6 +98,7 @@ def messages(db, data, media_folder, timezone_offset, filter_date, filter_chat, # Fetch the next row safely content = _fetch_row_safely(content_cursor) + _get_reactions(db, data) logger.info(f"Processed {total_row_number} messages{CLEAR_LINE}") @@ -480,6 +481,71 @@ def _format_message_text(text): return text +def _get_reactions(db, data): + """ + Process message reactions. + """ + logger.info("Processing reactions...") + c = db.cursor() + + try: + # Check if tables exist + c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='message_add_on'") + if c.fetchone()[0] == 0: + return + + c.execute(""" + SELECT + message_add_on.parent_message_row_id, + message_add_on_reaction.reaction, + message_add_on.from_me, + jid.raw_string as sender_jid_raw, + chat_jid.raw_string as chat_jid_raw + FROM message_add_on + INNER JOIN message_add_on_reaction + ON message_add_on._id = message_add_on_reaction.message_add_on_row_id + LEFT JOIN jid + ON message_add_on.sender_jid_row_id = jid._id + LEFT JOIN chat + ON message_add_on.chat_row_id = chat._id + LEFT JOIN jid chat_jid + ON chat.jid_row_id = chat_jid._id + """) + except sqlite3.OperationalError: + logger.warning("Could not fetch reactions (schema might be too old or incompatible).") + return + + row = c.fetchone() + while row is not None: + parent_id = row["parent_message_row_id"] + reaction = row["reaction"] + chat_id = row["chat_jid_raw"] + + if chat_id and chat_id in data: + chat = data[chat_id] + if parent_id in chat._messages: + message = chat._messages[parent_id] + + # Determine sender name + sender_name = None + if row["from_me"]: + sender_name = "You" + elif row["sender_jid_raw"]: + sender_jid = row["sender_jid_raw"] + if sender_jid in data: + sender_name = data[sender_jid].name + if not sender_name: + sender_name = sender_jid.split('@')[0] if "@" in sender_jid else sender_jid + + if not sender_name: + sender_name = "Unknown" + + message.reactions[sender_name] = reaction + + row = c.fetchone() + logger.info(f"Reactions processed.{CLEAR_LINE}") + + def media(db, data, media_folder, filter_date, filter_chat, filter_empty, separate_media=True): """ Process WhatsApp media files from the database. diff --git a/Whatsapp_Chat_Exporter/data_model.py b/Whatsapp_Chat_Exporter/data_model.py index 8747419..47034e6 100644 --- a/Whatsapp_Chat_Exporter/data_model.py +++ b/Whatsapp_Chat_Exporter/data_model.py @@ -338,6 +338,7 @@ class Message: self.caption = None self.thumb = None # Android specific self.sticker = False + self.reactions = {} def to_json(self) -> Dict[str, Any]: """Convert message to JSON-serializable dict.""" diff --git a/Whatsapp_Chat_Exporter/whatsapp.html b/Whatsapp_Chat_Exporter/whatsapp.html index 2aa2b7e..b4b9c8a 100644 --- a/Whatsapp_Chat_Exporter/whatsapp.html +++ b/Whatsapp_Chat_Exporter/whatsapp.html @@ -287,6 +287,15 @@ {% endif %}

{{ msg.time }}

+ {% if msg.reactions %} +
+ {% for sender, emoji in msg.reactions.items() %} +
+ {{ emoji }} +
+ {% endfor %} +
+ {% endif %} {% else %} @@ -356,6 +365,15 @@ {{ msg.time }} + {% if msg.reactions %} +
+ {% for sender, emoji in msg.reactions.items() %} +
+ {{ emoji }} +
+ {% endfor %} +
+ {% endif %}