""" Notes management API endpoints. """ from typing import List, Optional from pathlib import Path import os from fastapi import APIRouter, Depends, HTTPException, status, Query from fastapi.responses import FileResponse, JSONResponse from pydantic import BaseModel, HttpUrl, Field from sqlmodel import Session, select from src.db.database import get_session from src.db.models import User, Note from src.auth.dependencies import get_current_user from src.utils.logger import setup_logger from src.utils.config import settings logger = setup_logger(__name__) router = APIRouter(prefix="/notes", tags=["Notes"]) # --- New Models for File-based Notes --- class GeneratedNoteFile(BaseModel): filename: str title: str created_at: float size: int # --- Existing Models --- class CreateNoteRequest(BaseModel): video_url: HttpUrl = Field(..., description="YouTube video URL") video_title: str = Field(..., max_length=500, description="Video title") summary_text: str = Field(..., description="Generated study notes in markdown") video_duration: Optional[int] = Field(None, description="Video duration in seconds") language: str = Field( default="en", max_length=10, description="Video language code" ) class NoteResponse(BaseModel): id: int video_url: str video_title: str summary_text: str video_duration: Optional[int] language: str user_id: int created_at: str # ========================================== # ✅ NEW ENDPOINTS: Read from 'outputs' folder # ========================================== @router.get("/generated", response_model=List[GeneratedNoteFile]) async def list_generated_notes(): """ List all markdown files found in the 'outputs' directory. This bypasses the database to show files directly. """ notes = [] output_dir = settings.output_dir # Create directory if it doesn't exist if not output_dir.exists(): return [] # Scan for .md files # We look for files ending with _notes.md for file_path in output_dir.glob("*_notes.md"): try: # Try to read the first line to get a clean title content = file_path.read_text(encoding="utf-8") lines = content.split("\n") # Usually the first line is "# Title" title = lines[0].replace("#", "").strip() if lines else file_path.name stats = file_path.stat() notes.append( GeneratedNoteFile( filename=file_path.name, title=title if title else file_path.name, created_at=stats.st_mtime, size=stats.st_size, ) ) except Exception as e: logger.error(f"Error reading file {file_path}: {e}") continue # Sort by newest first notes.sort(key=lambda x: x.created_at, reverse=True) return notes @router.get("/generated/{filename}") async def get_generated_note_content(filename: str): """ Get the full content of a specific markdown file. """ # Security check: prevent directory traversal if ".." in filename or "/" in filename: raise HTTPException(status_code=400, detail="Invalid filename") file_path = settings.output_dir / filename if not file_path.exists(): raise HTTPException(status_code=404, detail="Note file not found") content = file_path.read_text(encoding="utf-8") return {"content": content, "filename": filename} # ========================================== # End of New Endpoints # ========================================== # ... (Database endpoints kept for compatibility if needed later) ... # You can leave the rest of the file as is, or I can include it below just in case. # For brevity, I'll include the standard DB create/get just to not break anything. @router.post("", response_model=NoteResponse, status_code=status.HTTP_201_CREATED) async def create_note( note_data: CreateNoteRequest, current_user: User = Depends(get_current_user), session: Session = Depends(get_session), ): new_note = Note( video_url=str(note_data.video_url), video_title=note_data.video_title, summary_text=note_data.summary_text, video_duration=note_data.video_duration, language=note_data.language, user_id=current_user.id, ) session.add(new_note) session.commit() session.refresh(new_note) return NoteResponse( id=new_note.id, video_url=new_note.video_url, video_title=new_note.video_title, summary_text=new_note.summary_text, video_duration=new_note.video_duration, language=new_note.language, user_id=new_note.user_id, created_at=str(new_note.created_at), )