LogicGoInfotechSpaces commited on
Commit
335104c
·
verified ·
1 Parent(s): 533b0a8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -33
app.py CHANGED
@@ -254,55 +254,76 @@ async def face_swap_api(
254
  source: UploadFile = File(...),
255
  target_category_id: str = Form(None),
256
  new_category_id: str = Form(None),
257
- user_id: Optional[str] = Form(None)
 
258
  ):
259
  start_time = datetime.utcnow()
260
 
261
  try:
262
- # ============ VALIDATION ============
 
 
263
  if target_category_id and new_category_id:
264
  raise HTTPException(400, "Provide only one of new_category_id or target_category_id.")
265
 
266
  if not target_category_id and not new_category_id:
267
  raise HTTPException(400, "Either new_category_id or target_category_id is required.")
268
 
269
- # Read source image
 
 
270
  src_bytes = await source.read()
271
  src_key = f"faceswap/source/{uuid.uuid4().hex}_{source.filename}"
272
- upload_to_spaces(src_bytes, src_key)
273
 
274
- # ============ CASE 1: MongoDB new_category_id ============
 
 
275
  if new_category_id:
276
- doc = await subcategories_col.find_one({"asset_images._id": ObjectId(new_category_id)})
 
 
 
277
 
278
  if not doc:
279
- raise HTTPException(404, "Asset image not found.")
280
 
281
- # find correct asset image
282
- asset = next((img for img in doc["asset_images"] if str(img["_id"]) == new_category_id), None)
 
 
 
283
 
284
  if not asset:
285
- raise HTTPException(404, "Asset image URL not found.")
286
 
 
287
  target_url = asset["url"]
288
- category_oid = doc["categoryId"] # REAL ObjectId
289
 
290
- # ---- MEDIA_CLICKS ONLY IF user_id EXISTS ----
 
 
 
 
 
291
  if user_id:
292
  try:
293
- user_id = user_id.strip()
294
- user_oid = ObjectId(user_id)
295
  now = datetime.utcnow()
296
 
297
  update_result = await media_clicks_col.update_one(
298
  {"userId": user_oid, "categories.categoryId": category_oid},
299
  {
300
- "$set": {"updatedAt": now, "categories.$.lastClickedAt": now},
 
 
 
301
  "$inc": {"categories.$.click_count": 1}
302
  }
303
  )
304
 
305
  if update_result.matched_count == 0:
 
306
  await media_clicks_col.update_one(
307
  {"userId": user_oid},
308
  {
@@ -319,62 +340,81 @@ async def face_swap_api(
319
  upsert=True
320
  )
321
 
322
- except Exception as err:
323
- logger.error(f"MEDIA_CLICK ERROR: {err}")
324
- # Do NOT break face-swap
325
 
326
- # ============ CASE 2: DigitalOcean target_category_id ============
 
 
327
  if target_category_id:
328
  client = get_spaces_client()
329
  base_prefix = "faceswap/target/"
330
- resp = client.list_objects_v2(Bucket=DO_SPACES_BUCKET, Prefix=base_prefix, Delimiter="/")
331
-
 
332
  categories = [p["Prefix"].split("/")[2] for p in resp.get("CommonPrefixes", [])]
 
333
  target_url = None
334
 
335
  for category in categories:
336
  original_prefix = f"faceswap/target/{category}/original/"
337
- original_files = client.list_objects_v2(Bucket=DO_SPACES_BUCKET, Prefix=original_prefix)
 
 
338
 
339
- for idx, obj in enumerate(sorted(original_files.get("Contents", [])), start=1):
 
 
340
  cid = f"{category.lower()}image_{idx}"
341
  if cid == target_category_id:
342
- filename = obj["Key"].split("/")[-1]
343
- target_url = f"{DO_SPACES_ENDPOINT}/{DO_SPACES_BUCKET}/{original_prefix}{filename}"
344
  break
345
 
346
  if target_url:
347
  break
348
 
349
  if not target_url:
350
- raise HTTPException(404, "Target categoryId not found.")
 
 
 
 
 
351
 
352
- # ============ DOWNLOAD TARGET IMAGE ============
353
- target_bytes = requests.get(target_url).content
354
- tgt_bgr = cv2.imdecode(np.frombuffer(target_bytes, np.uint8), cv2.IMREAD_COLOR)
355
  src_bgr = cv2.imdecode(np.frombuffer(src_bytes, np.uint8), cv2.IMREAD_COLOR)
 
356
 
357
  if src_bgr is None or tgt_bgr is None:
358
  raise HTTPException(400, "Invalid image data")
359
 
360
- # ============ FACE SWAP ============
361
  src_rgb = cv2.cvtColor(src_bgr, cv2.COLOR_BGR2RGB)
362
  tgt_rgb = cv2.cvtColor(tgt_bgr, cv2.COLOR_BGR2RGB)
363
 
 
 
 
364
  final_img, final_path, err = face_swap_and_enhance(src_rgb, tgt_rgb)
365
  if err:
366
  raise HTTPException(500, err)
367
 
368
- result_bytes = open(final_path, "rb").read()
369
- result_key = f"faceswap/result/{uuid.uuid4().hex}.png"
 
 
370
  result_url = upload_to_spaces(result_bytes, result_key)
371
 
372
- return {"result_key": result_key, "result_url": result_url}
 
 
 
373
 
374
  except Exception as e:
375
  raise HTTPException(500, f"Face swap failed: {str(e)}")
376
 
377
 
 
 
378
  # @fastapi_app.post("/face-swap", dependencies=[Depends(verify_token)])
379
  # async def face_swap_api(
380
  # source: UploadFile = File(...),
 
254
  source: UploadFile = File(...),
255
  target_category_id: str = Form(None),
256
  new_category_id: str = Form(None),
257
+ user_id: Optional[str] = Form(None),
258
+ credentials: HTTPAuthorizationCredentials = Security(security)
259
  ):
260
  start_time = datetime.utcnow()
261
 
262
  try:
263
+ # ------------------------------------------------------------------
264
+ # VALIDATION
265
+ # ------------------------------------------------------------------
266
  if target_category_id and new_category_id:
267
  raise HTTPException(400, "Provide only one of new_category_id or target_category_id.")
268
 
269
  if not target_category_id and not new_category_id:
270
  raise HTTPException(400, "Either new_category_id or target_category_id is required.")
271
 
272
+ # ------------------------------------------------------------------
273
+ # READ SOURCE IMAGE
274
+ # ------------------------------------------------------------------
275
  src_bytes = await source.read()
276
  src_key = f"faceswap/source/{uuid.uuid4().hex}_{source.filename}"
277
+ upload_to_spaces(src_bytes, src_key, content_type=source.content_type)
278
 
279
+ # ------------------------------------------------------------------
280
+ # CASE 1 : new_category_id → MongoDB lookup
281
+ # ------------------------------------------------------------------
282
  if new_category_id:
283
+
284
+ doc = await subcategories_col.find_one({
285
+ "asset_images._id": ObjectId(new_category_id)
286
+ })
287
 
288
  if not doc:
289
+ raise HTTPException(404, "Asset image not found in database")
290
 
291
+ # extract correct asset
292
+ asset = next(
293
+ (img for img in doc["asset_images"] if str(img["_id"]) == new_category_id),
294
+ None
295
+ )
296
 
297
  if not asset:
298
+ raise HTTPException(404, "Asset image URL not found")
299
 
300
+ # correct URL
301
  target_url = asset["url"]
 
302
 
303
+ # correct categoryId (ObjectId)
304
+ category_oid = doc["categoryId"] # <-- DO NOT CONVERT TO STRING
305
+
306
+ # ------------------------------------------------------------------
307
+ # MEDIA_CLICKS (ONLY IF user_id PRESENT)
308
+ # ------------------------------------------------------------------
309
  if user_id:
310
  try:
311
+ user_oid = ObjectId(user_id.strip())
 
312
  now = datetime.utcnow()
313
 
314
  update_result = await media_clicks_col.update_one(
315
  {"userId": user_oid, "categories.categoryId": category_oid},
316
  {
317
+ "$set": {
318
+ "updatedAt": now,
319
+ "categories.$.lastClickedAt": now
320
+ },
321
  "$inc": {"categories.$.click_count": 1}
322
  }
323
  )
324
 
325
  if update_result.matched_count == 0:
326
+ # category does not exist → push new entry
327
  await media_clicks_col.update_one(
328
  {"userId": user_oid},
329
  {
 
340
  upsert=True
341
  )
342
 
343
+ except Exception as media_err:
344
+ logger.error(f"MEDIA_CLICK ERROR: {media_err}")
345
+ # do NOT interrupt faceswap flow
346
 
347
+ # ------------------------------------------------------------------
348
+ # CASE 2 : target_category_id → DigitalOcean path (unchanged logic)
349
+ # ------------------------------------------------------------------
350
  if target_category_id:
351
  client = get_spaces_client()
352
  base_prefix = "faceswap/target/"
353
+ resp = client.list_objects_v2(
354
+ Bucket=DO_SPACES_BUCKET, Prefix=base_prefix, Delimiter="/"
355
+ )
356
  categories = [p["Prefix"].split("/")[2] for p in resp.get("CommonPrefixes", [])]
357
+
358
  target_url = None
359
 
360
  for category in categories:
361
  original_prefix = f"faceswap/target/{category}/original/"
362
+ original_objs = client.list_objects_v2(
363
+ Bucket=DO_SPACES_BUCKET, Prefix=original_prefix
364
+ ).get("Contents", [])
365
 
366
+ original_files = sorted([obj["Key"] for obj in original_objs])
367
+
368
+ for idx, file_key in enumerate(original_files, start=1):
369
  cid = f"{category.lower()}image_{idx}"
370
  if cid == target_category_id:
371
+ target_url = f"{DO_SPACES_ENDPOINT}/{DO_SPACES_BUCKET}/{file_key}"
 
372
  break
373
 
374
  if target_url:
375
  break
376
 
377
  if not target_url:
378
+ raise HTTPException(404, "Target categoryId not found")
379
+
380
+ # ------------------------------------------------------------------
381
+ # DOWNLOAD TARGET IMAGE
382
+ # ------------------------------------------------------------------
383
+ tgt_bytes = requests.get(target_url).content
384
 
 
 
 
385
  src_bgr = cv2.imdecode(np.frombuffer(src_bytes, np.uint8), cv2.IMREAD_COLOR)
386
+ tgt_bgr = cv2.imdecode(np.frombuffer(tgt_bytes, np.uint8), cv2.IMREAD_COLOR)
387
 
388
  if src_bgr is None or tgt_bgr is None:
389
  raise HTTPException(400, "Invalid image data")
390
 
 
391
  src_rgb = cv2.cvtColor(src_bgr, cv2.COLOR_BGR2RGB)
392
  tgt_rgb = cv2.cvtColor(tgt_bgr, cv2.COLOR_BGR2RGB)
393
 
394
+ # ------------------------------------------------------------------
395
+ # FACE SWAP EXECUTION
396
+ # ------------------------------------------------------------------
397
  final_img, final_path, err = face_swap_and_enhance(src_rgb, tgt_rgb)
398
  if err:
399
  raise HTTPException(500, err)
400
 
401
+ with open(final_path, "rb") as f:
402
+ result_bytes = f.read()
403
+
404
+ result_key = f"faceswap/result/{uuid.uuid4().hex}_enhanced.png"
405
  result_url = upload_to_spaces(result_bytes, result_key)
406
 
407
+ return {
408
+ "result_key": result_key,
409
+ "result_url": result_url
410
+ }
411
 
412
  except Exception as e:
413
  raise HTTPException(500, f"Face swap failed: {str(e)}")
414
 
415
 
416
+
417
+
418
  # @fastapi_app.post("/face-swap", dependencies=[Depends(verify_token)])
419
  # async def face_swap_api(
420
  # source: UploadFile = File(...),