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:
@@ -55,6 +55,12 @@ demo-load:
|
|||||||
demo-reset:
|
demo-reset:
|
||||||
docker exec intotheeast_grav bash -c "rm -rf /var/www/html/user/pages/01.trips/italy-2026-demo && cd /var/www/html && php bin/grav clearcache"
|
docker exec intotheeast_grav bash -c "rm -rf /var/www/html/user/pages/01.trips/italy-2026-demo && cd /var/www/html && php bin/grav clearcache"
|
||||||
|
|
||||||
|
pixelfed-import:
|
||||||
|
docker exec intotheeast_grav bash -c "which python3 || apt-get install -y python3 --no-install-recommends -q"
|
||||||
|
docker cp /home/mischa/Nextcloud/Downloads/pixelfed/pixelfed-statuses.json intotheeast_grav:/tmp/pixelfed-statuses.json
|
||||||
|
docker cp scripts/pixelfed-import.py intotheeast_grav:/tmp/pixelfed-import.py
|
||||||
|
docker exec -w /var/www/html intotheeast_grav python3 /tmp/pixelfed-import.py
|
||||||
|
|
||||||
# ── Content sync (user repo ↔ Gitea) ──────────────────────────────────────────
|
# ── Content sync (user repo ↔ Gitea) ──────────────────────────────────────────
|
||||||
|
|
||||||
content-push:
|
content-push:
|
||||||
|
|||||||
@@ -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