convert / app.py
webzepetoku's picture
Update app.py
ccfce3d verified
Raw
History Blame Contribute Delete
4.06 kB
import os
import shutil
import subprocess
import requests
import zipfile
import glob
import uuid
import boto3
from fastapi import FastAPI, BackgroundTasks
from pydantic import BaseModel
# --- CONFIG ---
os.chdir("/tmp")
os.environ["HOME"] = "/tmp"
os.environ["UNITY_PATH"] = "/opt/unity/Editor/Unity"
BASE_PROJECT_PATH = "/app/UnityProject"
R2_CONFIG = {
"account_id": "31f2970a3442da4e6f17f79064897226",
"access_key": "44613d17ec50941707a7ddd9b17944bc",
"secret_key": "50185c21ff5e4f53e412e2013305b6ab24b7eda16cc0d3dc66593eed64aa99a2",
"bucket_name": "zepeto-builds"
}
app = FastAPI()
class ConversionRequest(BaseModel):
file_url: str
filename: str
def upload_to_r2(local_path, r2_filename):
try:
s3 = boto3.client('s3', endpoint_url=f"https://{R2_CONFIG['account_id']}.r2.cloudflarestorage.com",
aws_access_key_id=R2_CONFIG['access_key'], aws_secret_access_key=R2_CONFIG['secret_key'])
s3.upload_file(local_path, R2_CONFIG['bucket_name'], f"packed/{r2_filename}")
print(f"βœ… [R2] Upload Sukses: packed/{r2_filename}", flush=True)
except Exception as e: print(f"❌ [R2] Gagal: {e}", flush=True)
def make_zepeto_archive(source_dir, output_file):
"""Membungkus folder InputRaw menjadi file .zepeto (ZIP)"""
with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as z:
for root, dirs, files in os.walk(source_dir):
for file in files:
# Jangan masukkan file manifest root Unity atau file log
if file.endswith((".manifest", ".txt")): continue
file_path = os.path.join(root, file)
z.write(file_path, os.path.relpath(file_path, source_dir))
def process_pipeline(req: ConversionRequest):
session_id = str(uuid.uuid4())[:8]
SESSION_PATH = f"/tmp/Project_{session_id}"
extract_tmp = f"/tmp/extract_{session_id}"
final_zepeto = f"/tmp/{req.filename}.zepeto"
try:
# 1. Download & Extract Repository
r = requests.get(req.file_url)
zip_tmp = f"/tmp/{session_id}.zip"
with open(zip_tmp, 'wb') as f: f.write(r.content)
os.makedirs(extract_tmp)
with zipfile.ZipFile(zip_tmp, 'r') as z: z.extractall(extract_tmp)
# 2. Setup Unity Project & Assets
shutil.copytree(BASE_PROJECT_PATH, SESSION_PATH, ignore=shutil.ignore_patterns("Library", "Temp"))
target_input = os.path.join(SESSION_PATH, "Assets", "InputRaw")
os.makedirs(target_input, exist_ok=True)
# Pindahkan SEMUA file asli (PNG, Meta, Prefab) ke InputRaw
for item in os.listdir(extract_tmp):
s = os.path.join(extract_tmp, item)
d = os.path.join(target_input, item)
if os.path.isdir(s): shutil.copytree(s, d)
else: shutil.copy2(s, d)
# 3. Jalankan Unity (Rimpang Poligon & Build Binary Platform)
print(f"πŸš€ [UNITY] Merampingkan Mesh & Membangun Platform...", flush=True)
subprocess.run([os.environ["UNITY_PATH"], "-batchmode", "-nographics", "-quit",
"-projectPath", SESSION_PATH, "-executeMethod", "TestBuilder.ManualConvert",
"-logFile", "/dev/stdout"], check=False)
# 4. PACKING (Membungkus folder InputRaw yang sudah lengkap menjadi .zepeto)
print(f"πŸ“¦ [PACKING] Membuat archive {req.filename}.zepeto...", flush=True)
make_zepeto_archive(target_input, final_zepeto)
# 5. UPLOAD HASIL KE R2
if os.path.exists(final_zepeto):
upload_to_r2(final_zepeto, f"{req.filename}.zepeto")
else:
print("❌ [FAIL] Gagal membuat file .zepeto", flush=True)
finally:
for p in [SESSION_PATH, extract_tmp, zip_tmp, final_zepeto]:
if os.path.exists(p): shutil.rmtree(p) if os.path.isdir(p) else os.remove(p)
@app.post("/convert")
async def api_convert(req: ConversionRequest, background_tasks: BackgroundTasks):
background_tasks.add_task(process_pipeline, req)
return {"status": "success"}