rairo commited on
Commit
2ca2fa8
Β·
verified Β·
1 Parent(s): 3724c78

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +57 -69
main.py CHANGED
@@ -615,170 +615,158 @@ def view_videos():
615
 
616
 
617
  #download archives endpoint
 
 
 
618
  @app.route('/api/download/story_archive/<story_id>', methods=['GET'])
619
  def download_story_archive(story_id):
620
  try:
 
 
621
  # --- Authentication ---
622
  auth_header = request.headers.get('Authorization', '')
623
  if not auth_header.startswith('Bearer '):
 
624
  return jsonify({'error': 'Missing or invalid token'}), 401
 
625
  token = auth_header.split(' ')[1]
626
  uid = verify_token(token)
627
  if not uid:
 
628
  return jsonify({'error': 'Invalid or expired token'}), 401
629
 
630
  # --- Fetch the Story ---
631
  stories_ref = db.reference('stories')
632
  story_record = stories_ref.child(story_id).get()
633
  if not story_record:
 
634
  return jsonify({'error': 'Story not found'}), 404
635
  if story_record.get('uid') != uid:
 
636
  return jsonify({'error': 'Unauthorized'}), 403
637
 
638
- # Prepare data
639
  full_text = story_record.get("full_story", "")
640
  sections = story_record.get("sections", [])
641
-
642
- # Derive a title from the first sentence
643
  split_sentences = full_text.split('.', 1)
644
  title = split_sentences[0].strip() if split_sentences and split_sentences[0].strip() else "Untitled"
 
645
 
646
- # ------------------------------------------------------------------
647
- # Create an in-memory ZIP
648
- # ------------------------------------------------------------------
649
  zip_buffer = io.BytesIO()
650
  with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zipf:
651
 
652
  # ======================
653
  # 1) Generate PDF
654
  # ======================
 
655
  pdf = FPDF()
656
  pdf.set_auto_page_break(auto=True, margin=15)
657
  pdf.add_page()
658
  pdf.set_font("Arial", size=12)
659
 
660
- # Basic info
661
- pdf.cell(0, 10, f"Story ID: {story_id}")
662
- pdf.ln()
663
- pdf.cell(0, 10, f"Title: {title}")
664
- pdf.ln(15)
665
-
666
- # Add the full story text with proper line breaks
667
  pdf.multi_cell(0, 10, "Full Story:")
668
- pdf.ln(5)
669
  pdf.multi_cell(0, 10, full_text)
670
- pdf.ln(10)
671
 
672
- # For each section, create a new page
 
673
  for idx, section_obj in enumerate(sections):
674
- # Each section is a dict with "section_text" and "image_url"
675
  section_text = section_obj.get("section_text", "")
676
  image_url = section_obj.get("image_url", "")
677
 
678
  pdf.add_page()
679
  pdf.set_font("Arial", style='B', size=14)
680
- pdf.cell(0, 10, f"Section {idx + 1}")
681
- pdf.ln(15)
682
  pdf.set_font("Arial", size=12)
683
  pdf.multi_cell(0, 10, section_text)
684
- pdf.ln(10)
685
 
686
- # If there's an image URL, download & embed in PDF
687
  if image_url:
688
  try:
689
- # Initialize Firebase Storage bucket
690
- bucket = storage.bucket()
691
-
692
- # Get the image file path from the URL
693
- # Firebase Storage URLs are in the format:
694
- # https://firebasestorage.googleapis.com/v0/b/[bucket]/o/[file_path]?[params]
695
- file_path = ""
696
- if '/o/' in image_url and '?' in image_url:
697
- file_path = image_url.split('/o/')[1].split('?')[0]
698
- file_path = urllib.parse.unquote(file_path)
699
-
700
- # Create a temporary file to hold the image
701
  with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file:
702
  temp_img_path = temp_file.name
703
-
704
- # Download the image to temp file
705
  blob = bucket.blob(file_path)
706
  blob.download_to_filename(temp_img_path)
707
 
708
- # Calculate appropriate image width and place it on the page
709
- page_width = pdf.w - 2*pdf.l_margin
710
- image_width = min(page_width - 20, 160) # Keep some margin
711
- pdf.image(temp_img_path, x=(pdf.w - image_width)/2, w=image_width)
712
-
713
- # Clean up temp file
714
  os.unlink(temp_img_path)
 
715
  except Exception as img_error:
716
- print(f"PDF image error: {str(img_error)}")
717
- pdf.ln(5)
718
- pdf.multi_cell(0, 10, f"[Image could not be included]")
719
 
720
  # Save PDF to memory
721
  pdf_buffer = io.BytesIO()
722
  pdf.output(pdf_buffer)
723
  pdf_buffer.seek(0)
724
- # Add PDF to the ZIP
725
  zipf.writestr(f"{story_id}.pdf", pdf_buffer.read())
 
726
 
727
  # ======================
728
  # 2) Generate a TXT file
729
  # ======================
 
730
  txt_content = f"Story ID: {story_id}\nTitle: {title}\n\nFull Story:\n\n{full_text}\n\n"
731
  for idx, section_obj in enumerate(sections):
732
  section_text = section_obj.get("section_text", "")
733
  txt_content += f"\n\nSection {idx + 1}:\n{section_text}"
734
  zipf.writestr(f"{story_id}.txt", txt_content)
 
735
 
736
  # ======================
737
- # 3) Download each section's image file to the ZIP
738
  # ======================
739
- bucket = storage.bucket()
740
  for idx, section_obj in enumerate(sections):
741
  image_url = section_obj.get("image_url", "")
742
  if image_url:
743
  try:
744
- # Extract file path from Firebase Storage URL
745
- file_path = ""
746
- if '/o/' in image_url and '?' in image_url:
747
- file_path = image_url.split('/o/')[1].split('?')[0]
748
- file_path = urllib.parse.unquote(file_path)
749
-
750
- # Get the blob and download as bytes
751
  blob = bucket.blob(file_path)
752
  image_data = blob.download_as_bytes()
753
  zipf.writestr(f"image_section_{idx + 1}.jpg", image_data)
754
- print(f"Added image for section {idx + 1}")
755
  except Exception as img_error:
756
- print(f"Error downloading image for section {idx + 1}: {str(img_error)}")
757
 
758
  # ======================
759
- # 4) Download each section's audio file to the ZIP
760
  # ======================
761
  for idx, section_obj in enumerate(sections):
762
  audio_url = section_obj.get("audio_url", "")
763
  if audio_url:
764
  try:
765
- # Extract file path from Firebase Storage URL
766
- file_path = ""
767
- if '/o/' in audio_url and '?' in audio_url:
768
- file_path = audio_url.split('/o/')[1].split('?')[0]
769
- file_path = urllib.parse.unquote(file_path)
770
-
771
- # Get the blob and download as bytes
772
  blob = bucket.blob(file_path)
773
  audio_data = blob.download_as_bytes()
774
  zipf.writestr(f"audio_section_{idx + 1}.mp3", audio_data)
775
- print(f"Added audio for section {idx + 1}")
776
  except Exception as audio_error:
777
- print(f"Error downloading audio for section {idx + 1}: {str(audio_error)}")
 
 
 
 
 
 
 
 
 
778
 
779
- # ------------------------------------------------------------------
780
  # Serve ZIP File
781
- # ------------------------------------------------------------------
782
  zip_buffer.seek(0)
783
  return send_file(
784
  zip_buffer,
@@ -788,7 +776,7 @@ def download_story_archive(story_id):
788
  )
789
 
790
  except Exception as e:
791
- import traceback
792
  traceback.print_exc()
793
  return jsonify({'error': str(e)}), 500
794
 
 
615
 
616
 
617
  #download archives endpoint
618
+
619
+ # Configure logging to a file
620
+
621
  @app.route('/api/download/story_archive/<story_id>', methods=['GET'])
622
  def download_story_archive(story_id):
623
  try:
624
+ logging.info(f"πŸ”Ή [START] Processing story {story_id}")
625
+
626
  # --- Authentication ---
627
  auth_header = request.headers.get('Authorization', '')
628
  if not auth_header.startswith('Bearer '):
629
+ logging.warning("❌ Missing or invalid token")
630
  return jsonify({'error': 'Missing or invalid token'}), 401
631
+
632
  token = auth_header.split(' ')[1]
633
  uid = verify_token(token)
634
  if not uid:
635
+ logging.warning("❌ Invalid or expired token")
636
  return jsonify({'error': 'Invalid or expired token'}), 401
637
 
638
  # --- Fetch the Story ---
639
  stories_ref = db.reference('stories')
640
  story_record = stories_ref.child(story_id).get()
641
  if not story_record:
642
+ logging.error(f"❌ Story {story_id} not found")
643
  return jsonify({'error': 'Story not found'}), 404
644
  if story_record.get('uid') != uid:
645
+ logging.warning(f"❌ Unauthorized access attempt for story {story_id}")
646
  return jsonify({'error': 'Unauthorized'}), 403
647
 
648
+ # Extract story details
649
  full_text = story_record.get("full_story", "")
650
  sections = story_record.get("sections", [])
 
 
651
  split_sentences = full_text.split('.', 1)
652
  title = split_sentences[0].strip() if split_sentences and split_sentences[0].strip() else "Untitled"
653
+ logging.info(f"πŸ“Œ Story title: {title}")
654
 
655
+ # Create ZIP buffer
 
 
656
  zip_buffer = io.BytesIO()
657
  with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zipf:
658
 
659
  # ======================
660
  # 1) Generate PDF
661
  # ======================
662
+ logging.info(f"πŸ“„ Generating PDF for {story_id}")
663
  pdf = FPDF()
664
  pdf.set_auto_page_break(auto=True, margin=15)
665
  pdf.add_page()
666
  pdf.set_font("Arial", size=12)
667
 
668
+ # Add story details
669
+ pdf.multi_cell(0, 10, f"Story ID: {story_id}")
670
+ pdf.multi_cell(0, 10, f"Title: {title}")
671
+ pdf.ln(10)
 
 
 
672
  pdf.multi_cell(0, 10, "Full Story:")
 
673
  pdf.multi_cell(0, 10, full_text)
 
674
 
675
+ # Add sections with images
676
+ bucket = storage.bucket()
677
  for idx, section_obj in enumerate(sections):
 
678
  section_text = section_obj.get("section_text", "")
679
  image_url = section_obj.get("image_url", "")
680
 
681
  pdf.add_page()
682
  pdf.set_font("Arial", style='B', size=14)
683
+ pdf.multi_cell(0, 10, f"Section {idx + 1}")
 
684
  pdf.set_font("Arial", size=12)
685
  pdf.multi_cell(0, 10, section_text)
 
686
 
687
+ # Download & embed images
688
  if image_url:
689
  try:
690
+ logging.info(f"πŸ“· Downloading image for section {idx + 1}")
691
+ file_path = image_url.split('/o/')[1].split('?')[0]
692
+ file_path = urllib.parse.unquote(file_path)
693
+
 
 
 
 
 
 
 
 
694
  with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file:
695
  temp_img_path = temp_file.name
696
+
 
697
  blob = bucket.blob(file_path)
698
  blob.download_to_filename(temp_img_path)
699
 
700
+ pdf.image(temp_img_path, x=10, w=100)
 
 
 
 
 
701
  os.unlink(temp_img_path)
702
+ logging.info(f"βœ… Image embedded in PDF for section {idx + 1}")
703
  except Exception as img_error:
704
+ logging.error(f"❌ Error embedding image for section {idx + 1}: {str(img_error)}")
 
 
705
 
706
  # Save PDF to memory
707
  pdf_buffer = io.BytesIO()
708
  pdf.output(pdf_buffer)
709
  pdf_buffer.seek(0)
 
710
  zipf.writestr(f"{story_id}.pdf", pdf_buffer.read())
711
+ logging.info(f"βœ… PDF added to ZIP for {story_id}")
712
 
713
  # ======================
714
  # 2) Generate a TXT file
715
  # ======================
716
+ logging.info(f"πŸ“„ Generating TXT for {story_id}")
717
  txt_content = f"Story ID: {story_id}\nTitle: {title}\n\nFull Story:\n\n{full_text}\n\n"
718
  for idx, section_obj in enumerate(sections):
719
  section_text = section_obj.get("section_text", "")
720
  txt_content += f"\n\nSection {idx + 1}:\n{section_text}"
721
  zipf.writestr(f"{story_id}.txt", txt_content)
722
+ logging.info(f"βœ… TXT added to ZIP for {story_id}")
723
 
724
  # ======================
725
+ # 3) Download section images
726
  # ======================
 
727
  for idx, section_obj in enumerate(sections):
728
  image_url = section_obj.get("image_url", "")
729
  if image_url:
730
  try:
731
+ logging.info(f"πŸ“· Downloading image for ZIP (section {idx + 1})")
732
+ file_path = image_url.split('/o/')[1].split('?')[0]
733
+ file_path = urllib.parse.unquote(file_path)
734
+
 
 
 
735
  blob = bucket.blob(file_path)
736
  image_data = blob.download_as_bytes()
737
  zipf.writestr(f"image_section_{idx + 1}.jpg", image_data)
738
+ logging.info(f"βœ… Image added to ZIP for section {idx + 1}")
739
  except Exception as img_error:
740
+ logging.error(f"❌ Error downloading image for section {idx + 1}: {str(img_error)}")
741
 
742
  # ======================
743
+ # 4) Download section audios
744
  # ======================
745
  for idx, section_obj in enumerate(sections):
746
  audio_url = section_obj.get("audio_url", "")
747
  if audio_url:
748
  try:
749
+ logging.info(f"πŸ”Š Downloading audio for ZIP (section {idx + 1})")
750
+ file_path = audio_url.split('/o/')[1].split('?')[0]
751
+ file_path = urllib.parse.unquote(file_path)
752
+
 
 
 
753
  blob = bucket.blob(file_path)
754
  audio_data = blob.download_as_bytes()
755
  zipf.writestr(f"audio_section_{idx + 1}.mp3", audio_data)
756
+ logging.info(f"βœ… Audio added to ZIP for section {idx + 1}")
757
  except Exception as audio_error:
758
+ logging.error(f"❌ Error downloading audio for section {idx + 1}: {str(audio_error)}")
759
+
760
+ # ------------------------
761
+ # Upload log to Firebase
762
+ # ------------------------
763
+ log_url = upload_log()
764
+ if log_url:
765
+ logging.info(f"πŸ“€ Log uploaded: {log_url}")
766
+ else:
767
+ logging.error("❌ Failed to upload log")
768
 
 
769
  # Serve ZIP File
 
770
  zip_buffer.seek(0)
771
  return send_file(
772
  zip_buffer,
 
776
  )
777
 
778
  except Exception as e:
779
+ logging.error(f"❌ ERROR: {str(e)}")
780
  traceback.print_exc()
781
  return jsonify({'error': str(e)}), 500
782