import os, shutil, subprocess, requests, zipfile, uuid from fastapi import FastAPI, BackgroundTasks from pydantic import BaseModel # ========================================== # PANEL CONFIG # ========================================== os.chdir("/tmp") os.environ["HOME"] = "/tmp" os.environ["UNITY_PATH"] = "/opt/unity/Editor/Unity" os.environ["PYTHONUNBUFFERED"] = "1" # Folder ini sekarang harus berisi Assets, Packages, ProjectSettings, DAN Library BASE_PROJECT_PATH = "/app/UnityProject" app = FastAPI() class ConversionRequest(BaseModel): file_url: str filename: str z_id: str z_pw: str def setup_license(): target_dir = "/tmp/.local/share/unity3d/Unity" source_ulf = "/app/Unity_lic.ulf" if os.path.exists(source_ulf): os.makedirs(target_dir, exist_ok=True) target_path = os.path.join(target_dir, "Unity_lic.ulf") shutil.copy2(source_ulf, target_path) os.chmod(target_path, 0o777) print(f"✅ [LICENSE] Lisensi aktif.", flush=True) @app.post("/convert") async def api_convert(req: ConversionRequest, background_tasks: BackgroundTasks): background_tasks.add_task(process_pipeline, req) return {"status": "processing"} def process_pipeline(req: ConversionRequest): setup_license() session_id = str(uuid.uuid4())[:8] SESSION_PATH = f"/tmp/Project_{session_id}" zip_tmp = f"/tmp/{session_id}.zepeto" extract_tmp = f"/tmp/extract_{session_id}" try: # 1. DOWNLOAD ASET BARU resp = requests.get(req.file_url, timeout=120) with open(zip_tmp, 'wb') as f: f.write(resp.content) os.makedirs(extract_tmp, exist_ok=True) with zipfile.ZipFile(zip_tmp, 'r') as z: z.extractall(extract_tmp) # 2. COPY TEMPLATE PROJECT (TERMASUK LIBRARY UNTUK CACHE) # Menghapus parameter ignore agar Library ikut tersalin if os.path.exists(SESSION_PATH): shutil.rmtree(SESSION_PATH) shutil.copytree(BASE_PROJECT_PATH, SESSION_PATH) # Pindahkan aset baru ke InputRaw target_in = os.path.join(SESSION_PATH, "Assets/InputRaw") os.makedirs(target_in, exist_ok=True) for item in os.listdir(extract_tmp): shutil.move(os.path.join(extract_tmp, item), os.path.join(target_in, item)) # 3. JALANKAN BUILD (Jauh lebih cepat karena Library sudah ada) print(f"🚀 [CLI] Memulai Build Studio untuk {req.z_id}...", flush=True) subprocess.run([ os.environ["UNITY_PATH"], "-batchmode", "-nographics", "-quit", "-projectPath", SESSION_PATH, "-executeMethod", "TestBuilder.ManualConvert", "-id", req.z_id, "-password", req.z_pw, "-job-worker-count", "4", "-logFile", "/dev/stdout" ], capture_output=False, check=True) print(f"✅ [SUCCESS] Pipeline Selesai dengan Cache.", flush=True) except Exception as e: print(f"🔥 [ERROR] Pipeline Gagal: {str(e)}", flush=True) finally: # Kita hapus SESSION_PATH, tapi BASE_PROJECT_PATH/Library tetap aman di /app/ if os.path.exists(SESSION_PATH): shutil.rmtree(SESSION_PATH) if os.path.exists(extract_tmp): shutil.rmtree(extract_tmp) if os.path.exists(zip_tmp): os.remove(zip_tmp) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)