Browse Source

Refactor media gallery generation to create a dedicated subdirectory and update HTML links for improved navigation

main
Andreas Demmelbauer 1 week ago
parent
commit
2305b66099
1 changed files with 76 additions and 72 deletions
  1. +76
    -72
      whatsapp_archiver.py

+ 76
- 72
whatsapp_archiver.py View File

@@ -115,13 +115,17 @@ def generate_all_media_gallery(db_path, output_dir):
end_idx = min(start_idx + items_per_page, total_media)
page_media_messages = valid_media_messages[start_idx:end_idx]

# Create media-gallery subdirectory
media_gallery_dir = os.path.join(output_dir, "media-gallery")
os.makedirs(media_gallery_dir, exist_ok=True)
# Determine filename
if page_num == 1:
filename = "media-gallery.html"
else:
filename = f"media-gallery-page-{page_num}.html"
media_gallery_path = os.path.join(output_dir, filename)
media_gallery_path = os.path.join(media_gallery_dir, filename)
with open(media_gallery_path, 'w', encoding='utf-8') as f:
f.write(f"""
@@ -288,8 +292,8 @@ def generate_all_media_gallery(db_path, output_dir):
<div class="header">
<h1>📷 Media Gallery</h1>
<div class="nav-links">
<a href="whatsapp-chats.html">← Back to Chats</a>
<a href="index.html">🏠 Home</a>
<a href="../whatsapp-chats.html">← Back to Chats</a>
<a href="../index.html">🏠 Home</a>
</div>
</div>
<div class="container">
@@ -387,10 +391,10 @@ def generate_all_media_gallery(db_path, output_dir):
<span class="sender-name">• {html.escape(str(sender_name))}</span>
<span class="timestamp">{convert_whatsapp_timestamp(message_date)}</span>
</div>
<a href="chats/{safe_filename}.html" style="text-decoration: none; color: inherit;">
<a href="../chats/{safe_filename}.html" style="text-decoration: none; color: inherit;">
{media_html}
</a>
<a href="../Message/{media_path}" target="_blank" class="raw-file-link">📁 Open File</a>
<a href="../../Message/{media_path}" target="_blank" class="raw-file-link">📁 Open File</a>
</div>
""")

@@ -613,7 +617,7 @@ def generate_chat_media_gallery(db_path, output_dir, chat_id, chat_name, contact
<h1>📷 Media from {html.escape(str(chat_name))}</h1>
<div class="nav-links">
<a href="../chats/{safe_filename}.html">← Back to Chat</a>
<a href="../media-gallery.html">🖼️ All Media</a>
<a href="../media-gallery/media-gallery.html">🖼️ All Media</a>
<a href="../whatsapp-chats.html">💬 All Chats</a>
</div>
</div>
@@ -881,7 +885,7 @@ def generate_html_chat(db_path, media_path, output_dir, chat_id, chat_name, is_g
{html.escape(chat_name)}
<div class="chat-header-id">{contact_jid}</div>
<div class="nav-links">
<a href="../whatsapp-chats.html">← Back</a>
<a href="../whatsapp-chats.html">← Back to Chats</a>
<a href="../media/{safe_filename}.html">📷 Media</a>
</div>
</div>
@@ -980,73 +984,73 @@ def process_iphone_backup(backup_path, output_dir):
'Sticker.sqlite'
]
# Prepare to recreate file structure
for fileID, domain, relativePath in files:
src_file = os.path.join(backup_path, fileID[:2], fileID)
dest_file = os.path.join(output_dir, relativePath)
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
# # Prepare to recreate file structure
# for fileID, domain, relativePath in files:
# src_file = os.path.join(backup_path, fileID[:2], fileID)
# dest_file = os.path.join(output_dir, relativePath)
# os.makedirs(os.path.dirname(dest_file), exist_ok=True)
if not os.path.exists(src_file):
# print(f"Source file missing: {src_file}")
skipped_files += 1
continue
# if not os.path.exists(src_file):
# # print(f"Source file missing: {src_file}")
# skipped_files += 1
# continue
# Handle SQLite database files specially - merge data instead of overwriting
file_basename = os.path.basename(dest_file)
if file_basename in db_files_to_merge and os.path.exists(dest_file):
special_db_files += 1
try:
# For SQLite databases, we need to merge the data
if file_basename == 'ChatStorage.sqlite':
merge_chat_database(src_file, dest_file)
else:
# For other SQLite databases, make a backup and then replace
# Future enhancement: implement proper merging for all database types
backup_file = f"{dest_file}.backup_{datetime.now().strftime('%Y%m%d%H%M%S')}"
shutil.copy2(dest_file, backup_file)
print(f"Created backup of {file_basename} as {os.path.basename(backup_file)}")
shutil.copy2(src_file, dest_file)
except Exception as e:
print(f"Error processing database {dest_file}: {e}")
continue
# # Handle SQLite database files specially - merge data instead of overwriting
# file_basename = os.path.basename(dest_file)
# if file_basename in db_files_to_merge and os.path.exists(dest_file):
# special_db_files += 1
# try:
# # For SQLite databases, we need to merge the data
# if file_basename == 'ChatStorage.sqlite':
# merge_chat_database(src_file, dest_file)
# else:
# # For other SQLite databases, make a backup and then replace
# # Future enhancement: implement proper merging for all database types
# backup_file = f"{dest_file}.backup_{datetime.now().strftime('%Y%m%d%H%M%S')}"
# shutil.copy2(dest_file, backup_file)
# print(f"Created backup of {file_basename} as {os.path.basename(backup_file)}")
# shutil.copy2(src_file, dest_file)
# except Exception as e:
# print(f"Error processing database {dest_file}: {e}")
# continue
# For non-database files
if os.path.exists(dest_file):
# If file exists, we want to keep the newer one
# For media files, we always keep them (accumulate data)
is_media_file = any(relativePath.startswith(prefix) for prefix in ['Media/', 'Message/', 'ProfilePictures/', 'Avatar/'])
# # For non-database files
# if os.path.exists(dest_file):
# # If file exists, we want to keep the newer one
# # For media files, we always keep them (accumulate data)
# is_media_file = any(relativePath.startswith(prefix) for prefix in ['Media/', 'Message/', 'ProfilePictures/', 'Avatar/'])
if is_media_file:
# For media files, don't overwrite but create a version with timestamp if different
if not files_are_identical(src_file, dest_file):
filename, ext = os.path.splitext(dest_file)
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
new_dest_file = f"{filename}_{timestamp}{ext}"
try:
shutil.copy2(src_file, new_dest_file)
print(f"Saved additional version of media file: {os.path.relpath(new_dest_file, output_dir)}")
new_files += 1
except Exception as e:
print(f"Error copying alternate version {src_file}: {e}")
skipped_files += 1
else:
skipped_files += 1
else:
# For non-media files, we'll take the newer one
try:
shutil.copy2(src_file, dest_file)
updated_files += 1
except Exception as e:
print(f"Error updating {dest_file}: {e}")
skipped_files += 1
else:
# If file doesn't exist, copy it
try:
shutil.copy2(src_file, dest_file)
new_files += 1
except Exception as e:
print(f"Error copying {src_file} to {dest_file}: {e}")
skipped_files += 1
# if is_media_file:
# # For media files, don't overwrite but create a version with timestamp if different
# if not files_are_identical(src_file, dest_file):
# filename, ext = os.path.splitext(dest_file)
# timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
# new_dest_file = f"{filename}_{timestamp}{ext}"
# try:
# shutil.copy2(src_file, new_dest_file)
# print(f"Saved additional version of media file: {os.path.relpath(new_dest_file, output_dir)}")
# new_files += 1
# except Exception as e:
# print(f"Error copying alternate version {src_file}: {e}")
# skipped_files += 1
# else:
# skipped_files += 1
# else:
# # For non-media files, we'll take the newer one
# try:
# shutil.copy2(src_file, dest_file)
# updated_files += 1
# except Exception as e:
# print(f"Error updating {dest_file}: {e}")
# skipped_files += 1
# else:
# # If file doesn't exist, copy it
# try:
# shutil.copy2(src_file, dest_file)
# new_files += 1
# except Exception as e:
# print(f"Error copying {src_file} to {dest_file}: {e}")
# skipped_files += 1
print(f"\nBackup import summary:")
print(f"- Added {new_files} new files")
@@ -1358,7 +1362,7 @@ def main():
<h1>WhatsApp Chat Export</h1>
<div class="export-info">Exported on {datetime.now().strftime('%Y-%m-%d %H:%M')}</div>
<div style="margin-top: 10px;">
<a href="media-gallery.html" style="color: rgba(255,255,255,0.9); text-decoration: none; padding: 5px 10px; border-radius: 5px; background-color: rgba(255,255,255,0.1);">📷 View All Media</a>
<a href="media-gallery/media-gallery.html" style="color: rgba(255,255,255,0.9); text-decoration: none; padding: 5px 10px; border-radius: 5px; background-color: rgba(255,255,255,0.1);">📷 View All Media</a>
</div>
</div>
<div class="container">
@@ -1464,7 +1468,7 @@ def main():
print(f" • {os.path.abspath(index_path)}")
print(f" • {os.path.abspath(redirect_index)}")
print(f"\nAdditional features:")
print(f" • Media Gallery: {os.path.abspath(os.path.join(args.output, 'media-gallery.html'))}")
print(f" • Media Gallery: {os.path.abspath(os.path.join(args.output, 'media-gallery', 'media-gallery.html'))}")
print(f" • Individual chat media galleries available in the media/ folder")




Loading…
Cancel
Save