feat: Add script to restore assets to MinIO and update DB URLs

This commit is contained in:
Apple
2025-12-02 13:45:14 -08:00
parent 8c801c1dab
commit b27bfc1df5

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env python3
"""
Відновлення assets: оновлення URLs в БД та завантаження файлів в MinIO
"""
import os
import sys
import asyncio
import asyncpg
from pathlib import Path
from typing import Optional
# Додати шлях до city-service для імпорту
sys.path.insert(0, str(Path(__file__).parent.parent / "services" / "city-service"))
try:
from lib.assets_client import upload_asset, ensure_bucket, settings
except ImportError as e:
print(f"❌ Помилка імпорту: {e}")
print("Переконайтеся що ви в правильній директорії та MinIO клієнт налаштований")
sys.exit(1)
# Маппінг старих URL на нові (якщо файли існують)
OLD_TO_NEW_MAPPING = {
"/assets/logos/clan.png": "clan",
"/assets/logos/soul.png": "soul",
"/assets/logos/yaromir.png": "yaromir",
"/assets/logos/druid.png": "druid",
"/assets/logos/nutra.png": "nutra",
"/assets/logos/eonarch.png": "eonarch",
"/assets/logos/helion.png": "energy-union",
"/assets/logos/greenfood.png": "greenfood",
"/assets/logos/daarion.png": "daarion",
}
async def update_database_urls(dry_run: bool = False):
"""Оновлює URLs в БД на правильні MinIO URLs"""
database_url = os.getenv(
"DATABASE_URL",
"postgresql://postgres:postgres@localhost:5432/daarion"
)
print("🔗 Підключення до БД...")
conn = await asyncpg.connect(database_url)
try:
# Отримуємо всі MicroDAO зі старими URL
rows = await conn.fetch("""
SELECT id, slug, logo_url, banner_url
FROM microdaos
WHERE logo_url IS NOT NULL OR banner_url IS NOT NULL
""")
print(f"📊 Знайдено {len(rows)} MicroDAO з assets")
updated_count = 0
for row in rows:
slug = row['slug']
logo_url = row['logo_url']
banner_url = row['banner_url']
updates = []
# Оновлюємо logo_url якщо потрібно
if logo_url and (logo_url.startswith('/assets/') or not logo_url.startswith('http')):
# Генеруємо новий URL для MinIO
new_logo_url = f"https://assets.daarion.space/daarion-assets/microdao/logo/{slug}.png"
if not dry_run:
# Спробуємо завантажити файл якщо він існує локально
local_paths = [
f"/opt/microdao-daarion/services/city-service/static/uploads/{slug}.png",
f"/opt/microdao-daarion/services/city-service/static/logos/{slug}.png",
f"/opt/microdao-daarion/public/assets/logos/{slug}.png",
]
uploaded = False
for local_path in local_paths:
if os.path.exists(local_path):
print(f" 📤 Завантажую логотип: {local_path}")
try:
with open(local_path, "rb") as f:
new_logo_url = upload_asset(
f,
"image/png",
"microdao/logo",
filename=f"{slug}.png"
)
uploaded = True
print(f" ✅ Завантажено: {new_logo_url}")
break
except Exception as e:
print(f" ⚠️ Помилка завантаження {local_path}: {e}")
if not uploaded:
print(f" ⚠️ Файл логотипу не знайдено для {slug}, використовую placeholder URL")
updates.append(f"logo_url = '{new_logo_url}'")
print(f" 🔄 {slug}: logo_url -> {new_logo_url}")
# Оновлюємо banner_url якщо потрібно
if banner_url and (banner_url.startswith('/api/static/') or not banner_url.startswith('http')):
# Генеруємо новий URL для MinIO
new_banner_url = f"https://assets.daarion.space/daarion-assets/microdao/banner/{slug}.png"
if not dry_run:
# Спробуємо завантажити файл якщо він існує локально
local_paths = [
f"/opt/microdao-daarion/services/city-service/static/uploads/{slug}_banner.png",
f"/opt/microdao-daarion/services/city-service/static/banners/{slug}.png",
]
uploaded = False
for local_path in local_paths:
if os.path.exists(local_path):
print(f" 📤 Завантажую банер: {local_path}")
try:
with open(local_path, "rb") as f:
new_banner_url = upload_asset(
f,
"image/png",
"microdao/banner",
filename=f"{slug}_banner.png"
)
uploaded = True
print(f" ✅ Завантажено: {new_banner_url}")
break
except Exception as e:
print(f" ⚠️ Помилка завантаження {local_path}: {e}")
if not uploaded:
print(f" ⚠️ Файл банера не знайдено для {slug}, залишаємо null")
new_banner_url = None
if new_banner_url:
updates.append(f"banner_url = '{new_banner_url}'")
print(f" 🔄 {slug}: banner_url -> {new_banner_url}")
else:
updates.append("banner_url = NULL")
print(f" 🔄 {slug}: banner_url -> NULL")
# Оновлюємо БД якщо є зміни
if updates:
if not dry_run:
update_sql = f"""
UPDATE microdaos
SET {', '.join(updates)}
WHERE id = $1
"""
await conn.execute(update_sql, row['id'])
updated_count += 1
else:
print(f" [DRY RUN] Would update: {slug}")
print(f"\n✅ Оновлено {updated_count} записів")
finally:
await conn.close()
def main():
import argparse
parser = argparse.ArgumentParser(description="Відновлення assets в MinIO та оновлення URLs в БД")
parser.add_argument(
"--dry-run",
action="store_true",
help="Тільки показати що буде зроблено, не змінювати БД"
)
args = parser.parse_args()
print("🚀 Відновлення assets")
print(f"🌐 MinIO Endpoint: {settings.minio_endpoint}")
print(f"🪣 Bucket: {settings.assets_bucket}")
print()
if not args.dry_run:
ensure_bucket()
print(f"✅ Bucket '{settings.assets_bucket}' готовий")
print()
asyncio.run(update_database_urls(dry_run=args.dry_run))
print("\n✅ Відновлення завершено")
print("\n💡 Якщо файли відсутні, потрібно:")
print(" 1. Завантажити логотипи/банери через UI")
print(" 2. Або створити placeholder зображення")
if __name__ == "__main__":
main()