Spaces:
Running
Running
push new changes
Browse files- .gitignore +1 -0
- READY_PLAYER_ME_FIXES.md β docs/READY_PLAYER_ME_FIXES.md +0 -0
- READY_PLAYER_ME_IMPLEMENTATION_SUMMARY.md β docs/READY_PLAYER_ME_IMPLEMENTATION_SUMMARY.md +0 -0
- READY_PLAYER_ME_INTEGRATION_PLAN.md β docs/READY_PLAYER_ME_INTEGRATION_PLAN.md +0 -0
- READY_PLAYER_ME_TESTING_GUIDE.md β docs/READY_PLAYER_ME_TESTING_GUIDE.md +0 -0
- WARDROBE_FEATURE_FLOW.md β docs/WARDROBE_FEATURE_FLOW.md +0 -0
- fashionclip +0 -1
- src/middleware/auth.ts +1 -1
- src/routes/auth.ts +2 -2
- src/routes/upload.ts +9 -25
- stylegpt +1 -0
- stylegptUI +0 -1
- test-ready-player-me.ts +0 -248
- test-upload.sh +0 -92
- test-upload.ts +0 -111
- tits.jpeg +0 -0
.gitignore
CHANGED
|
@@ -4,3 +4,4 @@ dist/
|
|
| 4 |
*.log
|
| 5 |
.DS_Store
|
| 6 |
|
|
|
|
|
|
| 4 |
*.log
|
| 5 |
.DS_Store
|
| 6 |
|
| 7 |
+
test/
|
READY_PLAYER_ME_FIXES.md β docs/READY_PLAYER_ME_FIXES.md
RENAMED
|
File without changes
|
READY_PLAYER_ME_IMPLEMENTATION_SUMMARY.md β docs/READY_PLAYER_ME_IMPLEMENTATION_SUMMARY.md
RENAMED
|
File without changes
|
READY_PLAYER_ME_INTEGRATION_PLAN.md β docs/READY_PLAYER_ME_INTEGRATION_PLAN.md
RENAMED
|
File without changes
|
READY_PLAYER_ME_TESTING_GUIDE.md β docs/READY_PLAYER_ME_TESTING_GUIDE.md
RENAMED
|
File without changes
|
WARDROBE_FEATURE_FLOW.md β docs/WARDROBE_FEATURE_FLOW.md
RENAMED
|
File without changes
|
fashionclip
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
Subproject commit b649345daaba74c3b65c85d28e6376c2b04c63c0
|
|
|
|
|
|
src/middleware/auth.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const authenticateToken = (
|
|
| 22 |
return res.status(401).json({ success: false, error: "No token provided" });
|
| 23 |
}
|
| 24 |
|
| 25 |
-
const jwtSecret = process.env.JWT_SECRET || "
|
| 26 |
|
| 27 |
jwt.verify(token, jwtSecret, (err: any, decoded: any) => {
|
| 28 |
if (err) {
|
|
|
|
| 22 |
return res.status(401).json({ success: false, error: "No token provided" });
|
| 23 |
}
|
| 24 |
|
| 25 |
+
const jwtSecret = process.env.JWT_SECRET || "";
|
| 26 |
|
| 27 |
jwt.verify(token, jwtSecret, (err: any, decoded: any) => {
|
| 28 |
if (err) {
|
src/routes/auth.ts
CHANGED
|
@@ -85,7 +85,7 @@ router.post("/register", async (req, res) => {
|
|
| 85 |
}
|
| 86 |
}
|
| 87 |
|
| 88 |
-
const jwtSecret = process.env.JWT_SECRET || "
|
| 89 |
const token = jwt.sign(
|
| 90 |
{ userId: newUser.id, email: newUser.email },
|
| 91 |
jwtSecret,
|
|
@@ -163,7 +163,7 @@ router.post("/login", async (req, res) => {
|
|
| 163 |
});
|
| 164 |
}
|
| 165 |
|
| 166 |
-
const jwtSecret = process.env.JWT_SECRET || "
|
| 167 |
const token = jwt.sign(
|
| 168 |
{ userId: user.id, email: user.email },
|
| 169 |
jwtSecret,
|
|
|
|
| 85 |
}
|
| 86 |
}
|
| 87 |
|
| 88 |
+
const jwtSecret = process.env.JWT_SECRET || "";
|
| 89 |
const token = jwt.sign(
|
| 90 |
{ userId: newUser.id, email: newUser.email },
|
| 91 |
jwtSecret,
|
|
|
|
| 163 |
});
|
| 164 |
}
|
| 165 |
|
| 166 |
+
const jwtSecret = process.env.JWT_SECRET || "";
|
| 167 |
const token = jwt.sign(
|
| 168 |
{ userId: user.id, email: user.email },
|
| 169 |
jwtSecret,
|
src/routes/upload.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
import express from "express";
|
| 2 |
import multer from "multer";
|
| 3 |
import { classifyFashionImage, identifyFashionItem } from "../utils/hfClient";
|
| 4 |
-
import { removeBackground } from "../utils/backgroundRemoval";
|
| 5 |
import { AppDataSource } from "../utils/dataSource";
|
| 6 |
import { WardrobeItem } from "../entity/WardrobeItem";
|
| 7 |
import { authenticateToken, AuthRequest } from "../middleware/auth";
|
|
@@ -55,17 +54,8 @@ router.post("/", authenticateToken, upload.array("image", 20), async (req: AuthR
|
|
| 55 |
try {
|
| 56 |
console.log(`Processing image ${i + 1}/${files.length}: ${file.originalname}`);
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
console.log(`Removing background for FashionClip classification: ${file.originalname}`);
|
| 61 |
-
processedBuffer = await removeBackground(file.buffer, file.originalname, file.mimetype);
|
| 62 |
-
console.log(`β
Background removed successfully for: ${file.originalname}`);
|
| 63 |
-
} catch (bgError: any) {
|
| 64 |
-
console.warn(`β οΈ Background removal failed for ${file.originalname}:`, bgError.message);
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
const imageForClassification = processedBuffer || file.buffer;
|
| 68 |
-
const imageMimeType = processedBuffer ? "image/png" : file.mimetype;
|
| 69 |
|
| 70 |
let color: string | null = null;
|
| 71 |
let itemLabel: string = "unknown";
|
|
@@ -134,9 +124,6 @@ router.post("/", authenticateToken, upload.array("image", 20), async (req: AuthR
|
|
| 134 |
const itemName = nameParts.join(" ");
|
| 135 |
|
| 136 |
const base64Image = `data:${file.mimetype};base64,${file.buffer.toString("base64")}`;
|
| 137 |
-
const processedBase64Image = processedBuffer
|
| 138 |
-
? `data:image/png;base64,${processedBuffer.toString("base64")}`
|
| 139 |
-
: undefined;
|
| 140 |
|
| 141 |
console.log(`β
Image converted to base64: ${itemName}`);
|
| 142 |
|
|
@@ -144,13 +131,10 @@ router.post("/", authenticateToken, upload.array("image", 20), async (req: AuthR
|
|
| 144 |
|
| 145 |
try {
|
| 146 |
console.log(`π Generating 3D model for: ${file.originalname}`);
|
| 147 |
-
const imageFor3D = processedBuffer || file.buffer;
|
| 148 |
-
const mimeTypeFor3D = processedBuffer ? "image/png" : file.mimetype;
|
| 149 |
-
|
| 150 |
const threeDResult = await generate3DModel(
|
| 151 |
-
|
| 152 |
file.originalname,
|
| 153 |
-
|
| 154 |
);
|
| 155 |
|
| 156 |
if (threeDResult && threeDResult.modelFile) {
|
|
@@ -172,7 +156,7 @@ router.post("/", authenticateToken, upload.array("image", 20), async (req: AuthR
|
|
| 172 |
|
| 173 |
const newItem = itemRepo.create({
|
| 174 |
imageUrl: base64Image,
|
| 175 |
-
processedImageUrl:
|
| 176 |
model3dUrl: model3dUrl,
|
| 177 |
category: normalizedCategory,
|
| 178 |
style: style,
|
|
@@ -206,15 +190,15 @@ router.post("/", authenticateToken, upload.array("image", 20), async (req: AuthR
|
|
| 206 |
console.log(` - 3D model uploaded: ${modelUrl}`);
|
| 207 |
|
| 208 |
// Upload icon image file
|
| 209 |
-
const
|
| 210 |
-
const
|
| 211 |
-
const iconMimeType = iconImage.startsWith('data:image/png') ? 'image/png' : 'image/jpeg';
|
| 212 |
const iconBuffer = Buffer.from(iconBase64Data, 'base64');
|
| 213 |
|
| 214 |
console.log(` - Uploading icon image (${iconBuffer.length} bytes, ${iconMimeType})...`);
|
|
|
|
| 215 |
const iconUrl = await readyPlayerMeClient.uploadAssetFile(
|
| 216 |
iconBuffer,
|
| 217 |
-
`${itemName.replace(/\s+/g, '-')}-icon.${
|
| 218 |
iconMimeType
|
| 219 |
);
|
| 220 |
|
|
|
|
| 1 |
import express from "express";
|
| 2 |
import multer from "multer";
|
| 3 |
import { classifyFashionImage, identifyFashionItem } from "../utils/hfClient";
|
|
|
|
| 4 |
import { AppDataSource } from "../utils/dataSource";
|
| 5 |
import { WardrobeItem } from "../entity/WardrobeItem";
|
| 6 |
import { authenticateToken, AuthRequest } from "../middleware/auth";
|
|
|
|
| 54 |
try {
|
| 55 |
console.log(`Processing image ${i + 1}/${files.length}: ${file.originalname}`);
|
| 56 |
|
| 57 |
+
const imageForClassification = file.buffer;
|
| 58 |
+
const imageMimeType = file.mimetype;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
let color: string | null = null;
|
| 61 |
let itemLabel: string = "unknown";
|
|
|
|
| 124 |
const itemName = nameParts.join(" ");
|
| 125 |
|
| 126 |
const base64Image = `data:${file.mimetype};base64,${file.buffer.toString("base64")}`;
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
console.log(`β
Image converted to base64: ${itemName}`);
|
| 129 |
|
|
|
|
| 131 |
|
| 132 |
try {
|
| 133 |
console.log(`π Generating 3D model for: ${file.originalname}`);
|
|
|
|
|
|
|
|
|
|
| 134 |
const threeDResult = await generate3DModel(
|
| 135 |
+
file.buffer,
|
| 136 |
file.originalname,
|
| 137 |
+
file.mimetype
|
| 138 |
);
|
| 139 |
|
| 140 |
if (threeDResult && threeDResult.modelFile) {
|
|
|
|
| 156 |
|
| 157 |
const newItem = itemRepo.create({
|
| 158 |
imageUrl: base64Image,
|
| 159 |
+
processedImageUrl: undefined,
|
| 160 |
model3dUrl: model3dUrl,
|
| 161 |
category: normalizedCategory,
|
| 162 |
style: style,
|
|
|
|
| 190 |
console.log(` - 3D model uploaded: ${modelUrl}`);
|
| 191 |
|
| 192 |
// Upload icon image file
|
| 193 |
+
const iconBase64Data = base64Image.split(',')[1];
|
| 194 |
+
const iconMimeType = file.mimetype;
|
|
|
|
| 195 |
const iconBuffer = Buffer.from(iconBase64Data, 'base64');
|
| 196 |
|
| 197 |
console.log(` - Uploading icon image (${iconBuffer.length} bytes, ${iconMimeType})...`);
|
| 198 |
+
const iconExtension = iconMimeType === 'image/png' ? 'png' : iconMimeType === 'image/jpeg' ? 'jpg' : 'jpg';
|
| 199 |
const iconUrl = await readyPlayerMeClient.uploadAssetFile(
|
| 200 |
iconBuffer,
|
| 201 |
+
`${itemName.replace(/\s+/g, '-')}-icon.${iconExtension}`,
|
| 202 |
iconMimeType
|
| 203 |
);
|
| 204 |
|
stylegpt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Subproject commit 4d69afdb3e0096392d36e3ca80aba65a5c501bd0
|
stylegptUI
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
Subproject commit 47bd250878e5dcecf1a829869686f27f8e79c560
|
|
|
|
|
|
test-ready-player-me.ts
DELETED
|
@@ -1,248 +0,0 @@
|
|
| 1 |
-
import dotenv from "dotenv";
|
| 2 |
-
import { ReadyPlayerMeClient } from "./src/utils/readyPlayerMe";
|
| 3 |
-
import fs from "fs";
|
| 4 |
-
import path from "path";
|
| 5 |
-
|
| 6 |
-
dotenv.config();
|
| 7 |
-
|
| 8 |
-
const READY_API_KEY = process.env.READY_API_KEY;
|
| 9 |
-
const READY_APPLICATION_ID = process.env.READY_PLAYER_ME_APPLICATION_ID;
|
| 10 |
-
const READY_ORGANIZATION_ID = process.env.READY_PLAYER_ME_ORGANIZATION_ID;
|
| 11 |
-
|
| 12 |
-
async function testReadyPlayerMeAPIs() {
|
| 13 |
-
console.log("=== Ready Player Me API Test Suite ===\n");
|
| 14 |
-
|
| 15 |
-
if (!READY_API_KEY) {
|
| 16 |
-
console.error("β READY_API_KEY not found in environment variables");
|
| 17 |
-
process.exit(1);
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
if (!READY_APPLICATION_ID) {
|
| 21 |
-
console.warn("β οΈ READY_PLAYER_ME_APPLICATION_ID not found - some tests will be skipped");
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
if (!READY_ORGANIZATION_ID) {
|
| 25 |
-
console.warn("β οΈ READY_PLAYER_ME_ORGANIZATION_ID not found - some tests will be skipped");
|
| 26 |
-
}
|
| 27 |
-
|
| 28 |
-
const client = new ReadyPlayerMeClient(READY_APPLICATION_ID);
|
| 29 |
-
|
| 30 |
-
let testGuestUserId: string | null = null;
|
| 31 |
-
let testAssetId: string | null = null;
|
| 32 |
-
let testAvatarId: string | null = null;
|
| 33 |
-
|
| 34 |
-
try {
|
| 35 |
-
console.log("1. Testing createGuestUser...");
|
| 36 |
-
if (READY_APPLICATION_ID) {
|
| 37 |
-
const guestUser = await client.createGuestUser(READY_APPLICATION_ID);
|
| 38 |
-
if (guestUser) {
|
| 39 |
-
testGuestUserId = guestUser.id;
|
| 40 |
-
console.log("β
Guest user created:", {
|
| 41 |
-
id: guestUser.id,
|
| 42 |
-
applicationIds: guestUser.applicationIds,
|
| 43 |
-
createdAt: guestUser.createdAt,
|
| 44 |
-
});
|
| 45 |
-
} else {
|
| 46 |
-
console.log("β Failed to create guest user");
|
| 47 |
-
}
|
| 48 |
-
} else {
|
| 49 |
-
console.log("βοΈ Skipped (no APPLICATION_ID)");
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
console.log("\n2. Testing getAvatarGLB (URL generation)...");
|
| 53 |
-
const testAvatarIdForURL = "test-avatar-id-123";
|
| 54 |
-
const glbUrl = await client.getAvatarGLB(testAvatarIdForURL, {
|
| 55 |
-
quality: "high",
|
| 56 |
-
lod: 0,
|
| 57 |
-
textureFormat: "webp",
|
| 58 |
-
});
|
| 59 |
-
console.log("β
GLB URL generated:", glbUrl);
|
| 60 |
-
console.log(" Expected format: https://avatars.readyplayer.me/{id}.glb?quality=high&lod=0&textureFormat=webp");
|
| 61 |
-
|
| 62 |
-
console.log("\n3. Testing getAvatar2DRender (URL generation)...");
|
| 63 |
-
const renderUrl = await client.getAvatar2DRender(testAvatarIdForURL, {
|
| 64 |
-
size: 400,
|
| 65 |
-
quality: 90,
|
| 66 |
-
camera: "portrait",
|
| 67 |
-
});
|
| 68 |
-
console.log("β
2D Render URL generated:", renderUrl);
|
| 69 |
-
console.log(" Expected format: https://models.readyplayer.me/{id}.png?size=400&quality=90&camera=portrait");
|
| 70 |
-
|
| 71 |
-
console.log("\n4. Testing getAvatarMetadata...");
|
| 72 |
-
if (testAvatarId) {
|
| 73 |
-
const metadata = await client.getAvatarMetadata(testAvatarId);
|
| 74 |
-
if (metadata) {
|
| 75 |
-
console.log("β
Avatar metadata retrieved:", {
|
| 76 |
-
id: metadata.id,
|
| 77 |
-
url: metadata.url,
|
| 78 |
-
});
|
| 79 |
-
} else {
|
| 80 |
-
console.log("β Failed to get avatar metadata (avatar may not exist)");
|
| 81 |
-
}
|
| 82 |
-
} else {
|
| 83 |
-
console.log("βοΈ Skipped (no test avatar ID - create an avatar first)");
|
| 84 |
-
console.log(" To test this, create an avatar via the Profile page and use its ID");
|
| 85 |
-
}
|
| 86 |
-
|
| 87 |
-
console.log("\n5. Testing uploadAssetFile...");
|
| 88 |
-
const testImagePath = path.join(__dirname, "tits.jpeg");
|
| 89 |
-
let uploadedUrl: string | null = null;
|
| 90 |
-
|
| 91 |
-
if (fs.existsSync(testImagePath)) {
|
| 92 |
-
const fileBuffer = fs.readFileSync(testImagePath);
|
| 93 |
-
uploadedUrl = await client.uploadAssetFile(
|
| 94 |
-
fileBuffer,
|
| 95 |
-
"test-upload.bin",
|
| 96 |
-
"application/octet-stream"
|
| 97 |
-
);
|
| 98 |
-
if (uploadedUrl) {
|
| 99 |
-
console.log("β
File uploaded to temporary storage");
|
| 100 |
-
console.log(" URL:", uploadedUrl.substring(0, 100) + "...");
|
| 101 |
-
console.log(" Note: This URL expires after 24 hours");
|
| 102 |
-
} else {
|
| 103 |
-
console.log("β Failed to upload file");
|
| 104 |
-
}
|
| 105 |
-
} else {
|
| 106 |
-
console.log("βοΈ Skipped (test file not found)");
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
console.log("\n6. Testing createAsset...");
|
| 110 |
-
if (READY_ORGANIZATION_ID) {
|
| 111 |
-
if (!uploadedUrl) {
|
| 112 |
-
console.log("β οΈ Note: Asset creation requires a valid GLB file URL.");
|
| 113 |
-
console.log(" In production, this comes from 3D model generation.");
|
| 114 |
-
console.log(" Testing with a placeholder URL (will fail validation)...");
|
| 115 |
-
}
|
| 116 |
-
|
| 117 |
-
const testModelUrl = uploadedUrl || "https://example.com/test-asset.glb";
|
| 118 |
-
const asset = await client.createAsset({
|
| 119 |
-
name: "Test Wardrobe Item",
|
| 120 |
-
type: "top",
|
| 121 |
-
gender: "neutral",
|
| 122 |
-
modelUrl: testModelUrl,
|
| 123 |
-
iconUrl: testModelUrl,
|
| 124 |
-
organizationId: READY_ORGANIZATION_ID,
|
| 125 |
-
locked: false,
|
| 126 |
-
applications: READY_APPLICATION_ID ? [{
|
| 127 |
-
id: READY_APPLICATION_ID,
|
| 128 |
-
organizationId: READY_ORGANIZATION_ID,
|
| 129 |
-
isVisibleInEditor: true,
|
| 130 |
-
}] : undefined,
|
| 131 |
-
});
|
| 132 |
-
|
| 133 |
-
if (asset) {
|
| 134 |
-
testAssetId = asset.id;
|
| 135 |
-
console.log("β
Asset created:", {
|
| 136 |
-
id: asset.id,
|
| 137 |
-
name: asset.name,
|
| 138 |
-
type: asset.type,
|
| 139 |
-
gender: asset.gender,
|
| 140 |
-
});
|
| 141 |
-
} else {
|
| 142 |
-
if (uploadedUrl) {
|
| 143 |
-
console.log("β Failed to create asset (uploaded file may not be a valid GLB)");
|
| 144 |
-
console.log(" This is expected if the uploaded file is not a GLB model.");
|
| 145 |
-
} else {
|
| 146 |
-
console.log("β Failed to create asset (placeholder URL rejected)");
|
| 147 |
-
}
|
| 148 |
-
}
|
| 149 |
-
} else {
|
| 150 |
-
console.log("βοΈ Skipped (no ORGANIZATION_ID)");
|
| 151 |
-
}
|
| 152 |
-
|
| 153 |
-
console.log("\n7. Testing listAssets...");
|
| 154 |
-
const assetsList = await client.listAssets({
|
| 155 |
-
limit: 5,
|
| 156 |
-
page: 1,
|
| 157 |
-
});
|
| 158 |
-
if (assetsList) {
|
| 159 |
-
console.log("β
Assets listed:", {
|
| 160 |
-
count: assetsList.data.length,
|
| 161 |
-
totalPages: assetsList.pagination?.totalPages || "unknown",
|
| 162 |
-
assets: assetsList.data.map(a => ({
|
| 163 |
-
id: a.id,
|
| 164 |
-
name: a.name,
|
| 165 |
-
type: a.type,
|
| 166 |
-
})),
|
| 167 |
-
});
|
| 168 |
-
} else {
|
| 169 |
-
console.log("β Failed to list assets");
|
| 170 |
-
}
|
| 171 |
-
|
| 172 |
-
console.log("\n8. Testing equipAsset (single)...");
|
| 173 |
-
if (testAvatarId && testAssetId) {
|
| 174 |
-
const equipSuccess = await client.equipAsset(testAvatarId, testAssetId);
|
| 175 |
-
if (equipSuccess) {
|
| 176 |
-
console.log("β
Asset equipped to avatar");
|
| 177 |
-
|
| 178 |
-
console.log("\n9. Testing unequipAsset...");
|
| 179 |
-
const unequipSuccess = await client.unequipAsset(testAvatarId, testAssetId);
|
| 180 |
-
if (unequipSuccess) {
|
| 181 |
-
console.log("β
Asset unequipped from avatar");
|
| 182 |
-
} else {
|
| 183 |
-
console.log("β Failed to unequip asset");
|
| 184 |
-
}
|
| 185 |
-
} else {
|
| 186 |
-
console.log("β Failed to equip asset");
|
| 187 |
-
}
|
| 188 |
-
} else {
|
| 189 |
-
console.log("βοΈ Skipped (no test avatar ID or asset ID)");
|
| 190 |
-
console.log(" To test this:");
|
| 191 |
-
console.log(" 1. Create an avatar via Profile page");
|
| 192 |
-
console.log(" 2. Upload a wardrobe item (creates an asset)");
|
| 193 |
-
console.log(" 3. Use those IDs to test equip/unequip");
|
| 194 |
-
}
|
| 195 |
-
|
| 196 |
-
console.log("\n10. Testing equipAsset (multiple assets)...");
|
| 197 |
-
if (testAvatarId && testAssetId) {
|
| 198 |
-
const equipPromises = [testAssetId].map(assetId =>
|
| 199 |
-
client.equipAsset(testAvatarId, assetId)
|
| 200 |
-
);
|
| 201 |
-
const results = await Promise.all(equipPromises);
|
| 202 |
-
const allSuccess = results.every(r => r === true);
|
| 203 |
-
if (allSuccess) {
|
| 204 |
-
console.log("β
Multiple assets equipped successfully");
|
| 205 |
-
} else {
|
| 206 |
-
console.log("β Some assets failed to equip");
|
| 207 |
-
}
|
| 208 |
-
} else {
|
| 209 |
-
console.log("βοΈ Skipped (no test avatar ID or asset ID)");
|
| 210 |
-
}
|
| 211 |
-
|
| 212 |
-
console.log("\n11. Testing getAuthToken...");
|
| 213 |
-
if (testGuestUserId) {
|
| 214 |
-
const token = await client.getAuthToken(testGuestUserId, "readyplayerme");
|
| 215 |
-
if (token) {
|
| 216 |
-
console.log("β
Auth token retrieved:", token.substring(0, 20) + "...");
|
| 217 |
-
} else {
|
| 218 |
-
console.log("β Failed to get auth token (may require specific partner permissions)");
|
| 219 |
-
console.log(" This is normal if your API key doesn't have token generation permissions");
|
| 220 |
-
}
|
| 221 |
-
} else {
|
| 222 |
-
console.log("βοΈ Skipped (no guest user ID)");
|
| 223 |
-
}
|
| 224 |
-
|
| 225 |
-
console.log("\n=== Test Summary ===");
|
| 226 |
-
console.log("β
URL generation tests passed");
|
| 227 |
-
console.log("β
API connectivity verified");
|
| 228 |
-
if (testGuestUserId) {
|
| 229 |
-
console.log("β
Guest user creation: PASSED");
|
| 230 |
-
}
|
| 231 |
-
if (testAssetId) {
|
| 232 |
-
console.log("β
Asset creation: PASSED");
|
| 233 |
-
}
|
| 234 |
-
console.log("\nNote: Some tests require real avatar/asset IDs from your application.");
|
| 235 |
-
console.log(" Run the full application flow to test equip/unequip functionality.");
|
| 236 |
-
|
| 237 |
-
} catch (error: any) {
|
| 238 |
-
console.error("\nβ Test suite error:", error.message);
|
| 239 |
-
if (error.response) {
|
| 240 |
-
console.error(" Response status:", error.response.status);
|
| 241 |
-
console.error(" Response data:", JSON.stringify(error.response.data, null, 2));
|
| 242 |
-
}
|
| 243 |
-
process.exit(1);
|
| 244 |
-
}
|
| 245 |
-
}
|
| 246 |
-
|
| 247 |
-
testReadyPlayerMeAPIs();
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test-upload.sh
DELETED
|
@@ -1,92 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
API_BASE_URL="https://nexusbert-stylegpt-milestone2.hf.space"
|
| 4 |
-
EMAIL="omezirizion@gmail.com"
|
| 5 |
-
PASSWORD="Amazon1@"
|
| 6 |
-
IMAGE_FILE="tits.jpeg"
|
| 7 |
-
|
| 8 |
-
echo "=== Testing Wardrobe Upload with tits.jpeg ==="
|
| 9 |
-
echo ""
|
| 10 |
-
|
| 11 |
-
# Step 1: Login
|
| 12 |
-
echo "1. Logging in..."
|
| 13 |
-
LOGIN_RESPONSE=$(curl -s -X POST "${API_BASE_URL}/api/auth/login" \
|
| 14 |
-
-H "Content-Type: application/json" \
|
| 15 |
-
-d "{\"email\":\"${EMAIL}\",\"password\":\"${PASSWORD}\"}")
|
| 16 |
-
|
| 17 |
-
echo "Login response: $LOGIN_RESPONSE"
|
| 18 |
-
echo ""
|
| 19 |
-
|
| 20 |
-
# Extract token (basic extraction, might need adjustment based on response format)
|
| 21 |
-
TOKEN=$(echo $LOGIN_RESPONSE | grep -o '"token":"[^"]*' | cut -d'"' -f4)
|
| 22 |
-
|
| 23 |
-
if [ -z "$TOKEN" ]; then
|
| 24 |
-
echo "β Failed to get token. Response: $LOGIN_RESPONSE"
|
| 25 |
-
exit 1
|
| 26 |
-
fi
|
| 27 |
-
|
| 28 |
-
echo "β
Login successful"
|
| 29 |
-
echo "Token: ${TOKEN:0:20}..."
|
| 30 |
-
echo ""
|
| 31 |
-
|
| 32 |
-
# Step 2: Check if file exists
|
| 33 |
-
if [ ! -f "$IMAGE_FILE" ]; then
|
| 34 |
-
echo "β File not found: $IMAGE_FILE"
|
| 35 |
-
exit 1
|
| 36 |
-
fi
|
| 37 |
-
|
| 38 |
-
echo "2. Found image file: $IMAGE_FILE"
|
| 39 |
-
echo ""
|
| 40 |
-
|
| 41 |
-
# Step 3: Upload
|
| 42 |
-
echo "3. Uploading image (this may take a while)..."
|
| 43 |
-
echo " - Background removal"
|
| 44 |
-
echo " - FashionClip classification"
|
| 45 |
-
echo " - 3D model generation"
|
| 46 |
-
echo " - Ready Player Me asset creation"
|
| 47 |
-
echo ""
|
| 48 |
-
|
| 49 |
-
UPLOAD_RESPONSE=$(curl -s -X POST "${API_BASE_URL}/api/upload" \
|
| 50 |
-
-H "Authorization: Bearer ${TOKEN}" \
|
| 51 |
-
-F "image=@${IMAGE_FILE}" \
|
| 52 |
-
-F "style=casual" \
|
| 53 |
-
--max-time 300)
|
| 54 |
-
|
| 55 |
-
echo "Upload response:"
|
| 56 |
-
echo "$UPLOAD_RESPONSE" | jq '.' 2>/dev/null || echo "$UPLOAD_RESPONSE"
|
| 57 |
-
echo ""
|
| 58 |
-
|
| 59 |
-
# Check if upload was successful
|
| 60 |
-
if echo "$UPLOAD_RESPONSE" | grep -q '"success":true'; then
|
| 61 |
-
echo "β
Upload successful!"
|
| 62 |
-
|
| 63 |
-
# Extract and display key information
|
| 64 |
-
if command -v jq &> /dev/null; then
|
| 65 |
-
echo ""
|
| 66 |
-
echo "π Results:"
|
| 67 |
-
COUNT=$(echo "$UPLOAD_RESPONSE" | jq -r '.count // "N/A"')
|
| 68 |
-
echo " - Items uploaded: $COUNT"
|
| 69 |
-
|
| 70 |
-
if [ "$COUNT" != "null" ] && [ "$COUNT" != "N/A" ]; then
|
| 71 |
-
ITEM_NAME=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].name // "N/A"')
|
| 72 |
-
CATEGORY=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].category // "N/A"')
|
| 73 |
-
STYLE=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].style // "N/A"')
|
| 74 |
-
COLOR=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].color // "N/A"')
|
| 75 |
-
HAS_3D=$(echo "$UPLOAD_RESPONSE" | jq -r 'if .items[0].model3dUrl then "Yes" else "No" end')
|
| 76 |
-
ASSET_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].readyPlayerMeAssetId // "N/A"')
|
| 77 |
-
ITEM_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.items[0].id // "N/A"')
|
| 78 |
-
|
| 79 |
-
echo " - Item name: $ITEM_NAME"
|
| 80 |
-
echo " - Category: $CATEGORY"
|
| 81 |
-
echo " - Style: $STYLE"
|
| 82 |
-
echo " - Color: $COLOR"
|
| 83 |
-
echo " - Has 3D model: $HAS_3D"
|
| 84 |
-
echo " - Ready Player Me Asset ID: $ASSET_ID"
|
| 85 |
-
echo " - Item ID: $ITEM_ID"
|
| 86 |
-
fi
|
| 87 |
-
fi
|
| 88 |
-
else
|
| 89 |
-
echo "β Upload failed"
|
| 90 |
-
exit 1
|
| 91 |
-
fi
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test-upload.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
| 1 |
-
import axios from "axios";
|
| 2 |
-
import FormData from "form-data";
|
| 3 |
-
import fs from "fs";
|
| 4 |
-
import path from "path";
|
| 5 |
-
import dotenv from "dotenv";
|
| 6 |
-
|
| 7 |
-
dotenv.config();
|
| 8 |
-
|
| 9 |
-
const API_BASE_URL = process.env.API_URL || "https://nexusbert-stylegpt-milestone2.hf.space";
|
| 10 |
-
const TEST_EMAIL = "omezirizion@gmail.com";
|
| 11 |
-
const TEST_PASSWORD = "Amazon1@";
|
| 12 |
-
|
| 13 |
-
async function testUpload() {
|
| 14 |
-
console.log("=== Testing Wardrobe Upload with tits.jpeg ===\n");
|
| 15 |
-
|
| 16 |
-
try {
|
| 17 |
-
// Step 1: Login to get token
|
| 18 |
-
console.log("1. Logging in...");
|
| 19 |
-
const loginResponse = await axios.post(`${API_BASE_URL}/api/auth/login`, {
|
| 20 |
-
email: TEST_EMAIL,
|
| 21 |
-
password: TEST_PASSWORD,
|
| 22 |
-
});
|
| 23 |
-
|
| 24 |
-
if (!loginResponse.data.success || !loginResponse.data.token) {
|
| 25 |
-
console.error("β Login failed:", loginResponse.data.error);
|
| 26 |
-
process.exit(1);
|
| 27 |
-
}
|
| 28 |
-
|
| 29 |
-
const token = loginResponse.data.token;
|
| 30 |
-
console.log("β
Login successful\n");
|
| 31 |
-
|
| 32 |
-
// Step 2: Check if file exists
|
| 33 |
-
const imagePath = path.join(__dirname, "tits.jpeg");
|
| 34 |
-
if (!fs.existsSync(imagePath)) {
|
| 35 |
-
console.error(`β File not found: ${imagePath}`);
|
| 36 |
-
process.exit(1);
|
| 37 |
-
}
|
| 38 |
-
console.log(`2. Found image file: ${imagePath}\n`);
|
| 39 |
-
|
| 40 |
-
// Step 3: Create form data
|
| 41 |
-
console.log("3. Preparing upload...");
|
| 42 |
-
const formData = new FormData();
|
| 43 |
-
formData.append("image", fs.createReadStream(imagePath), {
|
| 44 |
-
filename: "tits.jpeg",
|
| 45 |
-
contentType: "image/jpeg",
|
| 46 |
-
});
|
| 47 |
-
formData.append("style", "casual");
|
| 48 |
-
|
| 49 |
-
console.log("β
Form data prepared\n");
|
| 50 |
-
|
| 51 |
-
// Step 4: Upload
|
| 52 |
-
console.log("4. Uploading image (this may take a while)...");
|
| 53 |
-
console.log(" - Background removal");
|
| 54 |
-
console.log(" - FashionClip classification");
|
| 55 |
-
console.log(" - 3D model generation");
|
| 56 |
-
console.log(" - Ready Player Me asset creation\n");
|
| 57 |
-
|
| 58 |
-
const uploadResponse = await axios.post(
|
| 59 |
-
`${API_BASE_URL}/api/upload`,
|
| 60 |
-
formData,
|
| 61 |
-
{
|
| 62 |
-
headers: {
|
| 63 |
-
...formData.getHeaders(),
|
| 64 |
-
Authorization: `Bearer ${token}`,
|
| 65 |
-
},
|
| 66 |
-
maxContentLength: Infinity,
|
| 67 |
-
maxBodyLength: Infinity,
|
| 68 |
-
timeout: 300000, // 5 minutes timeout
|
| 69 |
-
}
|
| 70 |
-
);
|
| 71 |
-
|
| 72 |
-
if (uploadResponse.data.success) {
|
| 73 |
-
console.log("β
Upload successful!\n");
|
| 74 |
-
console.log("π Results:");
|
| 75 |
-
console.log(` - Items uploaded: ${uploadResponse.data.count}`);
|
| 76 |
-
if (uploadResponse.data.items && uploadResponse.data.items.length > 0) {
|
| 77 |
-
const item = uploadResponse.data.items[0];
|
| 78 |
-
console.log(` - Item name: ${item.name}`);
|
| 79 |
-
console.log(` - Category: ${item.category}`);
|
| 80 |
-
console.log(` - Style: ${item.style}`);
|
| 81 |
-
console.log(` - Color: ${item.color || "N/A"}`);
|
| 82 |
-
console.log(` - Has 3D model: ${item.model3dUrl ? "Yes" : "No"}`);
|
| 83 |
-
console.log(` - Ready Player Me Asset ID: ${item.readyPlayerMeAssetId || "N/A"}`);
|
| 84 |
-
console.log(` - Item ID: ${item.id}`);
|
| 85 |
-
}
|
| 86 |
-
if (uploadResponse.data.failed && uploadResponse.data.failed > 0) {
|
| 87 |
-
console.log(` - Failed files: ${uploadResponse.data.failed}`);
|
| 88 |
-
if (uploadResponse.data.failedFiles) {
|
| 89 |
-
console.log(` ${uploadResponse.data.failedFiles.join(", ")}`);
|
| 90 |
-
}
|
| 91 |
-
}
|
| 92 |
-
} else {
|
| 93 |
-
console.error("β Upload failed:", uploadResponse.data.error);
|
| 94 |
-
process.exit(1);
|
| 95 |
-
}
|
| 96 |
-
} catch (error: any) {
|
| 97 |
-
console.error("\nβ Error during upload test:");
|
| 98 |
-
if (error.response) {
|
| 99 |
-
console.error(` Status: ${error.response.status}`);
|
| 100 |
-
console.error(` Error: ${JSON.stringify(error.response.data, null, 2)}`);
|
| 101 |
-
} else if (error.request) {
|
| 102 |
-
console.error(" No response received. Is the server running?");
|
| 103 |
-
} else {
|
| 104 |
-
console.error(` ${error.message}`);
|
| 105 |
-
}
|
| 106 |
-
process.exit(1);
|
| 107 |
-
}
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
testUpload();
|
| 111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tits.jpeg
DELETED
|
Binary file (63.7 kB)
|
|
|