#!/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()