Files
Alex_Portfolio/backend/migrate_media_dropbox.py
T
StormRunner06106 6e3779e500 Banners, additional images, and files upload to Dropbox.
Dropbox file IDs are saved with the article in Supabase.
Banners appear in thumbnails and behind the article title/subtitle.
Additional images and files appear below the article text.
2026-09-13 08:58:09 -07:00

60 lines
2.7 KiB
Python

"""Migrate referenced local article media; originals are retained as backups."""
import argparse
import json
from dotenv import load_dotenv
from backend import main, dropbox_storage
def migrate(apply=False):
records = main.article_records()
media = {item["url"]: item for post in records for item in [post.get("banner"), *(post.get("attachments") or [])] if item}
local = [item for item in media.values() if item.get("storage") != "dropbox"]
print(f"{len(local)} local media references across {len(records)} articles.")
if not apply:
print("Preview only. Use --apply to upload files and update article metadata.")
return
dropbox_storage.get_dropbox() # Fail before modifying anything if not configured.
converted = {}
for item in local:
upload_id = item["url"].rsplit("/", 1)[-1]
stored = main.uploaded_media(upload_id)
if stored.get("storage") != "dropbox":
data = (main.UPLOAD_DIR / upload_id).read_bytes()
stored = {**stored, "storage": "dropbox", "dropbox_file_id": dropbox_storage.upload(data, upload_id, stored["name"])}
main.save_media_metadata(upload_id, stored)
# Keep old URLs working on this server too; retain the original bytes.
(main.UPLOAD_DIR / f"{upload_id}.json").write_text(json.dumps(stored), encoding="utf-8")
converted[item["url"]] = stored
client = main.get_supabase()
for post in records:
banner = post.get("banner")
attachments = post.get("attachments") or []
replacement = {
"banner": converted.get(banner["url"], banner) if banner else None,
"attachments": [converted.get(item["url"], item) for item in attachments],
}
if replacement == {"banner": banner, "attachments": attachments}:
continue
if client is not None:
result = client.table(main.articles_table()).update(replacement).eq("slug", post["slug"]).execute()
if not result.data:
raise RuntimeError("An article could not be updated. Retry the migration.")
else:
with main.POSTS_LOCK:
latest = json.loads(main.POSTS_PATH.read_text(encoding="utf-8"))
for current in latest:
if current["slug"] == post["slug"]:
current.update(replacement)
main.save_local_posts(latest)
print(f"Updated {len(converted)} media references. Original local files were retained.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--apply", action="store_true")
arguments = parser.parse_args()
load_dotenv(main.BASE_DIR / ".env")
migrate(arguments.apply)