study-notes-api / src /api /notes_routes.py
ALI7ADEL's picture
Upload 51 files
ed147e2 verified
"""
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),
)