# migrate_to_files.py - One-time: base64 in DB → files on disk (v4.2 → v4.3) import sqlite3 import base64 from config import DATABASE from db import init_db from media_storage import save_audio, save_image, save_thumbnail def migrate(): # নিশ্চিত করি নতুন কলামগুলো (audio_path, image_path, thumbnail_path) তৈরি আছে print("🔧 Ensuring schema is up to date...") init_db() conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row cur = conn.cursor() # --- Audio --- cur.execute(''' SELECT mb.id as block_id, mb.audio_data, mb.audio_format, c.project_id FROM markdown_blocks mb JOIN chapters c ON mb.chapter_id = c.id WHERE mb.audio_data IS NOT NULL AND mb.audio_data != '' AND (mb.audio_path IS NULL OR mb.audio_path = '') ''') rows = cur.fetchall() print(f"🔊 Migrating {len(rows)} audio blocks...") done = 0 for r in rows: try: rel = save_audio(r['project_id'], r['block_id'], r['audio_data'], r['audio_format'] or 'mp3') if rel: cur.execute("UPDATE markdown_blocks SET audio_path=?, audio_data='' WHERE id=?", (rel, r['block_id'])) done += 1 except Exception as e: print(f" ⚠️ Audio block {r['block_id']} failed: {e}") conn.commit() print(f" ✅ {done} audio files written") # --- Images --- cur.execute(''' SELECT bi.id as image_id, bi.image_data, bi.image_format, c.project_id FROM block_images bi JOIN markdown_blocks mb ON bi.block_id = mb.id JOIN chapters c ON mb.chapter_id = c.id WHERE bi.image_data IS NOT NULL AND bi.image_data != '' AND (bi.image_path IS NULL OR bi.image_path = '') ''') rows = cur.fetchall() print(f"🖼️ Migrating {len(rows)} images...") done = 0 for r in rows: try: rel = save_image(r['project_id'], r['image_id'], r['image_data'], r['image_format'] or 'png') if rel: cur.execute("UPDATE block_images SET image_path=?, image_data='' WHERE id=?", (rel, r['image_id'])) done += 1 except Exception as e: print(f" ⚠️ Image {r['image_id']} failed: {e}") conn.commit() print(f" ✅ {done} image files written") # --- Thumbnails --- cur.execute(''' SELECT id, thumbnail_data, thumbnail_format FROM projects WHERE thumbnail_data IS NOT NULL AND thumbnail_data != '' AND (thumbnail_path IS NULL OR thumbnail_path = '') ''') rows = cur.fetchall() print(f"📕 Migrating {len(rows)} thumbnails...") done = 0 for r in rows: try: raw = base64.b64decode(r['thumbnail_data']) rel = save_thumbnail(r['id'], raw, r['thumbnail_format'] or 'png') if rel: cur.execute("UPDATE projects SET thumbnail_path=?, thumbnail_data=NULL WHERE id=?", (rel, r['id'])) done += 1 except Exception as e: print(f" ⚠️ Thumbnail {r['id']} failed: {e}") conn.commit() print(f" ✅ {done} thumbnails written") print("🧹 Running VACUUM (this may take a while on a large DB)...") conn.execute('VACUUM') conn.commit() conn.close() print("✅ Migration complete! Database should now be much smaller.") if __name__ == '__main__': migrate()