feat: add pixelfed-import script and make target
Copies JSON export + script into Docker container and runs import via python3; installs python3 if absent. Idempotent (skips existing folders). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
"""One-time import of Pixelfed statuses into Grav entry pages."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
from datetime import datetime, timezone
|
||||
|
||||
INPUT_FILE = os.environ.get('PIXELFED_JSON', '/tmp/pixelfed-statuses.json')
|
||||
USER_PAGES = 'user/pages/01.trips'
|
||||
|
||||
TRIP_MAP = {
|
||||
'2023': 'central-asia-2023',
|
||||
'2024': 'us-canada-mex-2024',
|
||||
'2025': 'italy-2025',
|
||||
}
|
||||
|
||||
EXT_MAP = {
|
||||
'image/jpeg': 'jpg',
|
||||
'image/png': 'png',
|
||||
'image/gif': 'gif',
|
||||
'image/webp': 'webp',
|
||||
}
|
||||
|
||||
ENTRY_TEMPLATE = """\
|
||||
---
|
||||
title: '{title}'
|
||||
date: '{date}'
|
||||
template: entry
|
||||
published: true
|
||||
hero_image: '{hero_image}'
|
||||
lat: ''
|
||||
lng: ''
|
||||
location_city: '{location_city}'
|
||||
location_country: '{location_country}'
|
||||
weather_temp_c: ''
|
||||
weather_desc: ''
|
||||
---
|
||||
|
||||
{body}
|
||||
"""
|
||||
|
||||
|
||||
def download(url, dest):
|
||||
try:
|
||||
urllib.request.urlretrieve(url, dest)
|
||||
return True
|
||||
except Exception as exc:
|
||||
print(f' Warning: download failed {url}: {exc}')
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
with open(INPUT_FILE) as f:
|
||||
posts = json.load(f)
|
||||
|
||||
counters = {}
|
||||
|
||||
for post in posts:
|
||||
year = post['created_at'][:4]
|
||||
trip = TRIP_MAP.get(year)
|
||||
if not trip:
|
||||
print(f"Skip: no trip mapping for year {year} (post {post['id']})")
|
||||
continue
|
||||
|
||||
counters[trip] = counters.get(trip, 0) + 1
|
||||
n = counters[trip]
|
||||
|
||||
date_str = post['created_at'][:10] # YYYY-MM-DD
|
||||
folder = f'{date_str}-pixelfed-{n}.entry'
|
||||
path = os.path.join(USER_PAGES, trip, '01.dailies', folder)
|
||||
|
||||
if os.path.exists(path):
|
||||
print(f'Skip: {folder} already exists')
|
||||
continue
|
||||
|
||||
os.makedirs(path)
|
||||
print(f'Creating {trip}/{folder}')
|
||||
|
||||
hero_image = ''
|
||||
for i, att in enumerate(post.get('media_attachments', []), 1):
|
||||
ext = EXT_MAP.get(att.get('mime', ''), 'jpg')
|
||||
filename = f'photo-{i}.{ext}'
|
||||
if download(att['url'], os.path.join(path, filename)) and i == 1:
|
||||
hero_image = filename
|
||||
|
||||
place = post.get('place') or {}
|
||||
dt = datetime.fromisoformat(post['created_at'].replace('Z', '+00:00'))
|
||||
date_fmt = dt.strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
entry_md = ENTRY_TEMPLATE.format(
|
||||
title=f'Pixelfed Import {n}',
|
||||
date=date_fmt,
|
||||
hero_image=hero_image,
|
||||
location_city=place.get('name', ''),
|
||||
location_country=place.get('country', ''),
|
||||
body=post.get('content_text', '').strip(),
|
||||
)
|
||||
|
||||
with open(os.path.join(path, 'entry.md'), 'w') as f:
|
||||
f.write(entry_md)
|
||||
|
||||
print(f'\nDone. Posts per trip: {counters}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user