"""One-time migration of September 2026 uploads into individual highlighted photos.""" from datetime import datetime, timedelta, timezone from pathlib import Path import html import json import re ART = Path("_art") UPLOAD = "/img/arts/uploads" OLD = [ "260cc99527c13f256d4ea39d0959f5daa942c888ea882852e73fd94f6c30b7db", "474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c", "7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d", "b18a2f1c7127077c801160782012cb164759f0b9dd41762205b45e4c9a07d673", "c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b", ] armenia = [ (OLD[2], 9), (OLD[2], 8), (OLD[2], 7), (OLD[2], 6), (OLD[2], 5), (OLD[2], 4), (OLD[1], 0), ] romania = [ (OLD[2], 0), (OLD[2], 1), (OLD[4], 0), (OLD[4], 1), (OLD[4], 2), (OLD[4], 3), (OLD[4], 4), (OLD[0], 0), (OLD[3], 0), ] ungrouped = [(OLD[2], 2), (OLD[2], 3)] ordered = armenia + romania + ungrouped assert len(ordered) == len(set(ordered)) == 18 collection_groups = [ ( "iran-analog-2024", datetime(2024, 10, 25, 23, 59, 59, tzinfo=timezone.utc), "Iran - Hamadan, Kermanshah, Tabriz", [ "Taq-e-Bostan_000521270020.jpg", "Taq-e-Bostan_000521270019.jpg", "Taq-e-Bostan_000521270018.jpg", "Tabriz_000521270013.jpg", "Tabriz_000521270012.jpg", "Iran_000521270023.jpg", "Iran_000521270021.jpg", "Hamadan_000521270035.jpg", "Hamadan_000521270034.jpg", "Hamadan_000521270033.jpg", "Hamadan_000521270032.jpg", "Hamadan_000521270031.jpg", "Ganjname,-Hamadan_000521270029.jpg", "Cowboy-from-Hamadan_000521270030.jpg", "Bistoon_000521270027.jpg", "Bistoon_000521270026.jpg", "Bistoon_000521270025.jpg", "Bazaar-e-Tabriz_000521270010.jpg", "Bazaar-e-Tabriz_000521270009.jpg", "Bazaar-e-Tabriz_000521270008.jpg", ("dresden-prague-iran-2024", "Babataher.jpg"), ], ), ( "kazakhstan-2024", datetime(2024, 10, 9, 23, 59, 59, tzinfo=timezone.utc), "Kazakhstan - World Nomad Games", [ "x_DSC-0999.jpg", "x_DSC-0994.jpg", "World-Nomad-Games,-Kazakhstan_DSC-0685.jpg", "World-Nomad-Games,-Kazakhstan_DSC-0536.jpg", "World-Nomad-Games,-Kazakhstan_DSC-0472.jpg", "World-Nomad-Games,-Kazakhstan_DSC-0298.jpg", "World-Nomad-Games,-Kazakhstan_DSC-0251.jpg", "Kazakhstan_DSC-0870.jpg", "Kazakhstan_DSC-0865.jpg", ], ), ( "dresden-prague-iran-2024", datetime(2024, 10, 9, 23, 50, 59, tzinfo=timezone.utc), "Dresden & Berlin", [ "x_000512370028.jpg", "x_000512370027.jpg", "x_000512370026.jpg", "x_000512370024.jpg", "x_000512370022.jpg", "x_000512370013.jpg", "x_000512350002.jpg", "x_000512350001.jpg", "Let-me-tell-you-a-story_000512370015.jpg", "Dresden_000512370034.jpg", "Dresden_000512370033.jpg", "Dresden_000512370032.jpg", "Dresden_000512370019.jpg", "Dresden_000512370018.jpg", "Dresden_000512370017.jpg", "Dresden_000512370016.jpg", ], ), ( "dresden-prague-iran-2024", datetime(2024, 10, 9, 23, 40, 59, tzinfo=timezone.utc), "Iran - Tehran & Qom", [ "Home_000512360003.jpg", "Somewhere-in-Tehran_2.jpg", "Somewhere-in-Tehran.jpg", "Grandmother's-old-room.jpg", ], ), ( "dresden-prague-iran-2024", datetime(2024, 10, 9, 23, 30, 59, tzinfo=timezone.utc), "Prague", [ "x_000512370006.jpg", "x_000512370005.jpg", "x_000512370003.jpg", "Prague_000512370012.jpg", "Prague_000512360031.jpg", "Prague_000512360030.jpg", "Prague_000512360029.jpg", "Prague_000512360027.jpg", "Prague_000512360021.jpg", "Prague_000512360020.jpg", "Prague_000512360019.jpg", ], ), ( "dresden-prague-iran-2024", datetime(2024, 10, 9, 23, 20, 59, tzinfo=timezone.utc), "Belfast & Tallaght", [ "x_000512350014.jpg", "x_000512350012.jpg", "x_000512350011.jpg", "x_000512350006.jpg", "x_000512350004.jpg", "x_000512350003.jpg", "Bobby-Sands.jpg", "Belfast_000512350032.jpg", "Belfast_000512350027.jpg", "Belfast_000512350026.jpg", "Belfast_000512350022.jpg", "Belfast_000512350018.jpg", ], ), ] anchors = {armenia[0]: "Armenia", romania[0]: "Romania"} captions = {(OLD[2], 7): "Transmission of Flesh by Erfan Ashourioun"} first_for_job = {} for photo in ordered: first_for_job.setdefault(photo[0], photo) for job in OLD: batch = next(ART.glob(f"*-photo-{job}.md"), None) if batch: batch.unlink() start = datetime(2026, 9, 19, 12, 29, 33, tzinfo=timezone.utc) for position, (job, index) in enumerate(ordered): title = f"photo-{job}-{index:02}" if (job, index) == first_for_job[job]: title = f"photo-{job}" date = start - timedelta(seconds=position) lines = ["---", "layout: post", f'title: "{title}"', f'date: "{date.isoformat()}"', "categories: art"] if (job, index) in anchors: lines.append(f'anchor: "{anchors[(job, index)]}"') lines.extend(["---", ""]) if (job, index) == first_for_job[job] and (job, index) not in anchors: lines.extend([f'
', ""]) caption = captions.get((job, index), "") lines.append(f'

') if caption: lines.append(f'{html.escape(caption)}') target = ART / f"2026-09-19-photo-{job}-{index:02}.md" target.write_text("\n".join(lines) + "\n") for folder, group_start, anchor, filenames in collection_groups: for position, member in enumerate(filenames): member_folder, filename = member if isinstance(member, tuple) else (folder, member) image = f"/img/arts/{member_folder}/{filename}" matches = [path for path in ART.glob("*.md") if image in path.read_text()] assert len(matches) == 1, (image, matches) path = matches[0] content = path.read_text() date = group_start - timedelta(seconds=position) content = re.sub(r"^date:.*$", f'date: "{date.isoformat()}"', content, count=1, flags=re.MULTILINE) content = re.sub(r"^anchor:.*\n", "", content, flags=re.MULTILINE) if position == 0: content = content.replace("categories: art\n", "categories: art\nanchor: " + json.dumps(anchor) + "\n", 1) path.write_text(content) print("Organized all configured photo highlights into contiguous groups")