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"}