Welcome to the {game_name} Archive
Select a channel from the sidebar list on the left to view specific round logs. Your scroll positions will remain locked automatically as you switch.
import os import glob import re import sys import urllib.request import urllib.parse import html # Add this new import! def get_channel_id(filename): match = re.search(r'\[(\d+)\]\.html$', filename) if match: return int(match.group(1)) return float('inf') def download_and_localize_images(target_dir, log_files): img_dir_name = "images" img_dir_path = os.path.join(target_dir, img_dir_name) os.makedirs(img_dir_path, exist_ok=True) downloaded_urls = {} img_counter = 0 print("Scanning log files for external images to download locally...") src_pattern = re.compile(r'src=["\'](https?://[^"\']+)["\']', re.IGNORECASE) for file_path in log_files: filename = os.path.basename(file_path) print(f" Processing image links in: {filename}") with open(file_path, "r", encoding="utf-8") as f: html_content = f.read() urls = src_pattern.findall(html_content) if not urls: continue modified = False for url in urls: if url.startswith(('data:', 'file:', './')) or url in downloaded_urls: if url in downloaded_urls: html_content = html_content.replace(url, downloaded_urls[url]) modified = True continue try: parsed_url = urllib.parse.urlparse(url) clean_path = parsed_url.path ext = os.path.splitext(clean_path)[1] if '?' in ext: ext = ext.split('?')[0] if not ext or len(ext) > 5: ext = ".png" img_counter += 1 local_img_name = f"img_{img_counter:04d}{ext}" local_img_path = os.path.join(img_dir_path, local_img_name) req = urllib.request.Request( html.unescape(url), headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'} ) with urllib.request.urlopen(req, timeout=10) as response, open(local_img_path, "wb") as out_file: out_file.write(response.read()) relative_local_path = f"{img_dir_name}/{local_img_name}" downloaded_urls[url] = relative_local_path html_content = html_content.replace(url, relative_local_path) modified = True except Exception as e: print(f" Warning: Could not download asset {url}... Error: {e}") if modified: with open(file_path, "w", encoding="utf-8") as f: f.write(html_content) print(f"Successfully cached {img_counter} image assets locally.") def build_discord_archive(target_dir, game_name): target_dir = os.path.abspath(target_dir) if not os.path.isdir(target_dir): print(f"Error: The directory '{target_dir}' does not exist.") return all_html_files = glob.glob(os.path.join(target_dir, "*.html")) exclude_files = {"index.html", "sidebar.html", "welcome.html", "public_index.html"} log_files = [f for f in all_html_files if os.path.basename(f) not in exclude_files] if not log_files: print(f"No Discord chat log HTML files found in '{target_dir}'.") return # Download image resources locally download_and_localize_images(target_dir, log_files) # Sort files chronologically by channel ID log_files.sort(key=lambda x: get_channel_id(os.path.basename(x))) print(f"Compiling Single Page Application layout for '{game_name}'...") sidebar_buttons = [] chat_panels = [] for idx, file_path in enumerate(log_files): filename = os.path.basename(file_path) clean_name = filename.split(" - ")[-1].split(" [")[0] if not clean_name or clean_name.endswith(".html"): clean_name = os.path.splitext(filename)[0] clean_name = clean_name.replace('"', '"') with open(file_path, "r", encoding="utf-8") as f: raw_html = f.read() body_match = re.search(r"
]*>(.*)", raw_html, re.DOTALL | re.IGNORECASE) body_content = body_match.group(1) if body_match else raw_html panel_id = f"chan_panel_{idx}" btn_html = f' ' sidebar_buttons.append(btn_html) panel_html = f' ' chat_panels.append(panel_html) sidebar_content_block = "\n".join(sidebar_buttons) chat_panels_block = "\n".join(chat_panels) master_spa_tmpl = f"""Select a channel from the sidebar list on the left to view specific round logs. Your scroll positions will remain locked automatically as you switch.