Spaces:
Running
Running
File size: 4,559 Bytes
ef96d38 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import os
import shutil
import subprocess
import json
import time
import requests
from fastapi import FastAPI, BackgroundTasks, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from playwright.sync_api import sync_playwright
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# --- KONFIGURASI ---
UNITY_PATH = "/opt/unity/Editor/Unity"
PROJECT_PATH = "/app/UnityProject"
TEMP_DIR = "/tmp/zepeto_work"
os.makedirs(TEMP_DIR, exist_ok=True)
# --- MODEL DATA (Sesuai dengan kiriman Cloudflare + Cloudinary) ---
class ConversionRequest(BaseModel):
file_url: str # URL dari Cloudinary
filename: str # Nama file (contoh: baju_keren.fbx)
zepeto_id: str
zepeto_password: str
# --- FUNGSI: LOGIN & UPLOAD KE ZEPETO STUDIO ---
def upload_to_zepeto(file_path, z_id, z_pw):
print(f"π [Zepeto] Mencoba login untuk: {z_id}")
try:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True, args=['--no-sandbox'])
context = browser.new_context(user_agent="Mozilla/5.0...")
page = context.new_page()
# Login Process
page.goto("https://account.zepeto.me/signin?sm=1")
page.fill('input[name="userId"]', z_id)
page.fill('input[type="password"]', z_pw)
page.click('button[type="submit"]')
# Tunggu Token/Cookie
page.wait_for_url(lambda u: "signin" not in u, timeout=15000)
cookies = context.cookies()
jwt_token = next((c['value'] for c in cookies if c['name'] == 'token'), None)
browser.close()
if not jwt_token:
return False, "Gagal mendapatkan JWT Token"
# API Upload Zepeto Studio
print("π [Zepeto] Mengirim file ke Studio API...")
upload_url = "https://cf-api-studio.zepeto.me/api/items"
headers = {"Authorization": f"Bearer {jwt_token}"}
with open(file_path, "rb") as f:
files = {"file": (os.path.basename(file_path), f, "application/octet-stream")}
res = requests.post(upload_url, headers=headers, files=files)
if res.status_code in [200, 201]:
return True, "Sukses Upload"
else:
return False, f"API Error: {res.text}"
except Exception as e:
return False, str(e)
# --- FUNGSI UTAMA: DOWNLOAD -> UNITY -> UPLOAD ---
def process_pipeline(req: ConversionRequest):
local_fbx = os.path.join(PROJECT_PATH, "Assets", req.filename)
output_filename = req.filename.replace(".fbx", ".zepeto")
local_zepeto = os.path.join(PROJECT_PATH, "output", output_filename)
try:
# 1. DOWNLOAD DARI CLOUDINARY
print(f"π₯ [Cloudinary] Downloading: {req.filename}")
r = requests.get(req.file_url, stream=True)
with open(local_fbx, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
# 2. JALANKAN UNITY (Konversi & Optimasi Poligon)
print("βοΈ [Unity] Memulai konversi & optimasi...")
# Perhatikan: Method C# harus menangani decimation/polygon reduction
cmd = [
UNITY_PATH, "-batchmode", "-nographics",
"-projectPath", PROJECT_PATH,
"-executeMethod", "TestBuilder.ManualConvert",
"-inputFile", req.filename,
"-quit", "-logFile", "-"
]
result = subprocess.run(cmd, capture_output=True, text=True)
if not os.path.exists(local_zepeto):
print(f"β [Unity] Gagal. Log: {result.stdout}")
return
# 3. UPLOAD KE ZEPETO STUDIO
success, msg = upload_to_zepeto(local_zepeto, req.z_id, req.z_pw)
if success:
print(f"β
[FINAL] {req.filename} Berhasil dikirim ke Zepeto!")
else:
print(f"β [FINAL] Gagal upload ke Zepeto Studio: {msg}")
except Exception as e:
print(f"β [CRITICAL] Pipeline Error: {e}")
finally:
# Cleanup
if os.path.exists(local_fbx): os.remove(local_fbx)
@app.post("/convert")
async def api_convert(req: ConversionRequest, background_tasks: BackgroundTasks):
background_tasks.add_task(process_pipeline, req)
return {"status": "success", "message": "Proses konversi dan upload Zepeto dimulai di background"} |