rairo commited on
Commit
29f3cee
·
verified ·
1 Parent(s): 519780f

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +101 -57
main.py CHANGED
@@ -404,8 +404,6 @@ def delete_sozo_project(project_id):
404
  logger.error(f"CRITICAL ERROR during delete project {project_id}: {traceback.format_exc()}")
405
  return jsonify({'error': str(e)}), 500
406
 
407
- # In main.py
408
-
409
  @app.route('/api/sozo/projects/<string:project_id>/generate-report', methods=['POST'])
410
  def generate_sozo_report(project_id):
411
  logger.info(f"POST /api/sozo/projects/{project_id}/generate-report - Received request")
@@ -416,6 +414,16 @@ def generate_sozo_report(project_id):
416
  if not uid:
417
  return jsonify({'error': 'Unauthorized'}), 401
418
 
 
 
 
 
 
 
 
 
 
 
419
  project_ref = db.reference(f'sozo_projects/{project_id}')
420
  project_data = project_ref.get()
421
 
@@ -454,11 +462,15 @@ def generate_sozo_report(project_id):
454
 
455
  project_ref.update(update_data)
456
 
457
- logger.info(f"Project {project_id} successfully updated with draft data.")
 
 
 
458
 
459
  return jsonify({
460
  'success': True,
461
- 'project': {**project_data, **update_data}
 
462
  }), 200
463
 
464
  except Exception as e:
@@ -478,6 +490,16 @@ def generate_sozo_video(project_id):
478
  uid = verify_token(token)
479
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
480
 
 
 
 
 
 
 
 
 
 
 
481
  project_ref = db.reference(f'sozo_projects/{project_id}')
482
  project_data = project_ref.get()
483
  if not project_data or project_data.get('uid') != uid: return jsonify({'error': 'Project not found or unauthorized'}), 404
@@ -506,13 +528,87 @@ def generate_sozo_video(project_id):
506
  if not video_url: raise Exception("Video generation failed in core function.")
507
 
508
  project_ref.update({'status': 'video_complete', 'videoUrl': video_url})
509
- return jsonify({'success': True, 'video_url': video_url}), 200
 
 
 
 
 
 
 
 
510
 
511
  except Exception as e:
512
  db.reference(f'sozo_projects/{project_id}').update({'status': 'failed', 'error': str(e)})
513
  traceback.print_exc()
514
  return jsonify({'error': str(e)}), 500
515
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
  @app.route('/api/sozo/projects/<string:project_id>/charts', methods=['POST'])
517
  def regenerate_sozo_chart(project_id):
518
  logger.info(f"Endpoint /charts POST for project {project_id}")
@@ -622,58 +718,6 @@ def update_narration_audio(project_id):
622
  logger.error(f"CRITICAL ERROR updating narration for {project_id}: {traceback.format_exc()}")
623
  return jsonify({'error': str(e)}), 500
624
 
625
- # In main.py, add this new endpoint
626
-
627
- @app.route('/api/sozo/projects/<string:project_id>/generate-slides', methods=['POST'])
628
- def generate_sozo_slides(project_id):
629
- logger.info(f"POST /api/sozo/projects/{project_id}/generate-slides - Generating slides")
630
- try:
631
- token = request.headers.get('Authorization', '').split(' ')
632
- uid = verify_token(token)
633
- if not uid:
634
- return jsonify({'error': 'Unauthorized'}), 401
635
-
636
- project_ref = db.reference(f'sozo_projects/{project_id}')
637
- project_data = project_ref.get()
638
-
639
- if not project_data or project_data.get('uid') != uid:
640
- return jsonify({'error': 'Project not found or unauthorized'}), 404
641
-
642
- raw_md = project_data.get('rawMarkdown')
643
- chart_urls = project_data.get('chartUrls', {})
644
-
645
- if not raw_md:
646
- return jsonify({'error': 'Report must be generated before slides can be created.'}), 400
647
-
648
- # The planner AI needs an LLM instance
649
- llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", google_api_key=os.getenv("GOOGLE_API_KEY"), temperature=0.2)
650
-
651
- slides_data = generate_slides_from_report(
652
- raw_md,
653
- chart_urls,
654
- uid,
655
- project_id,
656
- bucket,
657
- llm
658
- )
659
-
660
- if not slides_data:
661
- raise Exception("Slide generation failed in core function.")
662
-
663
- # Save the slides data to the project in Firebase
664
- project_ref.update({'slides': slides_data})
665
-
666
- logger.info(f"Project {project_id} successfully updated with {len(slides_data)} slides.")
667
-
668
- return jsonify({
669
- 'success': True,
670
- 'slides': slides_data
671
- }), 200
672
-
673
- except Exception as e:
674
- logger.error(f"CRITICAL error generating slides for project {project_id}: {traceback.format_exc()}")
675
- db.reference(f'sozo_projects/{project_id}').update({'status': 'failed_slides', 'error': str(e)})
676
- return jsonify({'error': str(e)}), 500
677
  # -----------------------------------------------------------------------------
678
  # 5. UNIVERSAL ENDPOINTS (Waitlist, Feedback, Credits)
679
  # -----------------------------------------------------------------------------
 
404
  logger.error(f"CRITICAL ERROR during delete project {project_id}: {traceback.format_exc()}")
405
  return jsonify({'error': str(e)}), 500
406
 
 
 
407
  @app.route('/api/sozo/projects/<string:project_id>/generate-report', methods=['POST'])
408
  def generate_sozo_report(project_id):
409
  logger.info(f"POST /api/sozo/projects/{project_id}/generate-report - Received request")
 
414
  if not uid:
415
  return jsonify({'error': 'Unauthorized'}), 401
416
 
417
+ # Check user credits first
418
+ user_ref = db.reference(f'users/{uid}')
419
+ user_data = user_ref.get()
420
+ if not user_data:
421
+ return jsonify({'error': 'User not found'}), 404
422
+
423
+ current_credits = user_data.get('credits', 0)
424
+ if current_credits < 2:
425
+ return jsonify({'error': 'Insufficient credits. Report generation requires 2 credits.'}), 402
426
+
427
  project_ref = db.reference(f'sozo_projects/{project_id}')
428
  project_data = project_ref.get()
429
 
 
462
 
463
  project_ref.update(update_data)
464
 
465
+ # Deduct credits ONLY after successful generation
466
+ user_ref.update({'credits': current_credits - 2})
467
+
468
+ logger.info(f"Project {project_id} successfully updated with draft data. User {uid} charged 2 credits.")
469
 
470
  return jsonify({
471
  'success': True,
472
+ 'project': {**project_data, **update_data},
473
+ 'credits_remaining': current_credits - 2
474
  }), 200
475
 
476
  except Exception as e:
 
490
  uid = verify_token(token)
491
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
492
 
493
+ # Check user credits first
494
+ user_ref = db.reference(f'users/{uid}')
495
+ user_data = user_ref.get()
496
+ if not user_data:
497
+ return jsonify({'error': 'User not found'}), 404
498
+
499
+ current_credits = user_data.get('credits', 0)
500
+ if current_credits < 5:
501
+ return jsonify({'error': 'Insufficient credits. Video generation requires 5 credits.'}), 402
502
+
503
  project_ref = db.reference(f'sozo_projects/{project_id}')
504
  project_data = project_ref.get()
505
  if not project_data or project_data.get('uid') != uid: return jsonify({'error': 'Project not found or unauthorized'}), 404
 
528
  if not video_url: raise Exception("Video generation failed in core function.")
529
 
530
  project_ref.update({'status': 'video_complete', 'videoUrl': video_url})
531
+
532
+ # Deduct credits ONLY after successful generation
533
+ user_ref.update({'credits': current_credits - 5})
534
+
535
+ return jsonify({
536
+ 'success': True,
537
+ 'video_url': video_url,
538
+ 'credits_remaining': current_credits - 5
539
+ }), 200
540
 
541
  except Exception as e:
542
  db.reference(f'sozo_projects/{project_id}').update({'status': 'failed', 'error': str(e)})
543
  traceback.print_exc()
544
  return jsonify({'error': str(e)}), 500
545
 
546
+
547
+ @app.route('/api/sozo/projects/<string:project_id>/generate-slides', methods=['POST'])
548
+ def generate_sozo_slides(project_id):
549
+ logger.info(f"POST /api/sozo/projects/{project_id}/generate-slides - Generating slides")
550
+ try:
551
+ token = request.headers.get('Authorization', '').split(' ')
552
+ uid = verify_token(token)
553
+ if not uid:
554
+ return jsonify({'error': 'Unauthorized'}), 401
555
+
556
+ # Check user credits first
557
+ user_ref = db.reference(f'users/{uid}')
558
+ user_data = user_ref.get()
559
+ if not user_data:
560
+ return jsonify({'error': 'User not found'}), 404
561
+
562
+ current_credits = user_data.get('credits', 0)
563
+ if current_credits < 5:
564
+ return jsonify({'error': 'Insufficient credits. Slide generation requires 5 credits.'}), 402
565
+
566
+ project_ref = db.reference(f'sozo_projects/{project_id}')
567
+ project_data = project_ref.get()
568
+
569
+ if not project_data or project_data.get('uid') != uid:
570
+ return jsonify({'error': 'Project not found or unauthorized'}), 404
571
+
572
+ raw_md = project_data.get('rawMarkdown')
573
+ chart_urls = project_data.get('chartUrls', {})
574
+
575
+ if not raw_md:
576
+ return jsonify({'error': 'Report must be generated before slides can be created.'}), 400
577
+
578
+ # The planner AI needs an LLM instance
579
+ llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", google_api_key=os.getenv("GOOGLE_API_KEY"), temperature=0.2)
580
+
581
+ slides_data = generate_slides_from_report(
582
+ raw_md,
583
+ chart_urls,
584
+ uid,
585
+ project_id,
586
+ bucket,
587
+ llm
588
+ )
589
+
590
+ if not slides_data:
591
+ raise Exception("Slide generation failed in core function.")
592
+
593
+ # Save the slides data to the project in Firebase
594
+ project_ref.update({'slides': slides_data})
595
+
596
+ # Deduct credits ONLY after successful generation
597
+ user_ref.update({'credits': current_credits - 5})
598
+
599
+ logger.info(f"Project {project_id} successfully updated with {len(slides_data)} slides. User {uid} charged 5 credits.")
600
+
601
+ return jsonify({
602
+ 'success': True,
603
+ 'slides': slides_data,
604
+ 'credits_remaining': current_credits - 5
605
+ }), 200
606
+
607
+ except Exception as e:
608
+ logger.error(f"CRITICAL error generating slides for project {project_id}: {traceback.format_exc()}")
609
+ db.reference(f'sozo_projects/{project_id}').update({'status': 'failed_slides', 'error': str(e)})
610
+ return jsonify({'error': str(e)}), 500
611
+
612
  @app.route('/api/sozo/projects/<string:project_id>/charts', methods=['POST'])
613
  def regenerate_sozo_chart(project_id):
614
  logger.info(f"Endpoint /charts POST for project {project_id}")
 
718
  logger.error(f"CRITICAL ERROR updating narration for {project_id}: {traceback.format_exc()}")
719
  return jsonify({'error': str(e)}), 500
720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  # -----------------------------------------------------------------------------
722
  # 5. UNIVERSAL ENDPOINTS (Waitlist, Feedback, Credits)
723
  # -----------------------------------------------------------------------------