This commit is contained in:
Leon
2025-07-15 22:54:35 +02:00
commit f7eda17284
89 changed files with 18535 additions and 0 deletions

View File

@@ -0,0 +1 @@
"""API routers for the application."""

View File

@@ -0,0 +1,25 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import Response
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.logging import get_logger
from app.services.feed_generator import generate_feed
logger = get_logger(__name__)
router = APIRouter()
@router.get("/feeds/{newsletter_id}")
def get_newsletter_feed(newsletter_id: int, db: Session = Depends(get_db)):
"""Generate an Atom feed for a specific newsletter."""
logger.info(f"Generating feed for newsletter_id={newsletter_id}")
feed = generate_feed(db, newsletter_id)
if not feed:
logger.warning(
f"Newsletter with id={newsletter_id} not found, cannot generate feed."
)
raise HTTPException(status_code=404, detail="Newsletter not found")
logger.info(f"Successfully generated feed for newsletter_id={newsletter_id}")
return Response(content=feed, media_type="application/atom+xml")

View File

@@ -0,0 +1,13 @@
from fastapi import APIRouter
from app.core.logging import get_logger
logger = get_logger(__name__)
router = APIRouter()
@router.get("/health")
def health_check():
"""Perform a health check of the API."""
logger.info("Health check endpoint called")
return {"status": "ok"}

View File

@@ -0,0 +1,73 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.imap import _test_imap_connection, get_folders
from app.core.logging import get_logger
from app.crud.settings import create_or_update_settings, get_settings
from app.schemas.settings import Settings, SettingsCreate
logger = get_logger(__name__)
router = APIRouter()
@router.get("/imap/settings", response_model=Settings)
def read_settings(db: Session = Depends(get_db)):
"""Retrieve IMAP settings."""
logger.info("Request to read IMAP settings")
settings = get_settings(db)
if not settings:
logger.warning("IMAP settings not found")
raise HTTPException(status_code=404, detail="IMAP settings not found")
return settings
@router.post("/imap/settings", response_model=Settings)
def update_settings(settings: SettingsCreate, db: Session = Depends(get_db)):
"""Update IMAP settings."""
logger.info("Request to update IMAP settings")
return create_or_update_settings(db=db, settings=settings)
@router.post("/imap/test")
def test_connection(db: Session = Depends(get_db)):
"""Test the IMAP connection with current settings."""
logger.info("Request to test IMAP connection")
settings = get_settings(db, with_password=True)
if not settings:
logger.error("IMAP settings not found, cannot test connection")
raise HTTPException(status_code=404, detail="IMAP settings not found")
is_successful, message = _test_imap_connection(
server=settings.imap_server,
username=settings.imap_username,
password=settings.imap_password,
)
if not is_successful:
logger.warning(f"IMAP connection test failed: {message}")
raise HTTPException(status_code=400, detail=message)
logger.info("IMAP connection test successful")
return {"message": message}
@router.get("/imap/folders", response_model=List[str])
def read_folders(db: Session = Depends(get_db)):
"""Retrieve a list of IMAP folders from the configured server."""
logger.info("Request to fetch IMAP folders")
settings = get_settings(db, with_password=True)
if not settings:
logger.error("IMAP settings not found, cannot fetch folders")
raise HTTPException(status_code=404, detail="IMAP settings not found")
folders = get_folders(
server=settings.imap_server,
username=settings.imap_username,
password=settings.imap_password,
)
logger.info(f"Found {len(folders)} IMAP folders")
return folders

View File

@@ -0,0 +1,72 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.logging import get_logger
from app.crud.newsletters import (
create_newsletter,
delete_newsletter,
get_newsletter,
get_newsletters,
update_newsletter,
)
from app.schemas.newsletters import Newsletter, NewsletterCreate, NewsletterUpdate
logger = get_logger(__name__)
router = APIRouter()
@router.post("/newsletters", response_model=Newsletter)
def create_new_newsletter(newsletter: NewsletterCreate, db: Session = Depends(get_db)):
"""Create a new newsletter."""
logger.info(
f"Request to create new newsletter for senders {newsletter.sender_emails}"
)
return create_newsletter(db=db, newsletter=newsletter)
@router.get("/newsletters", response_model=List[Newsletter])
def read_newsletters(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""Retrieve a list of newsletters."""
logger.info(f"Request to read newsletters with skip={skip}, limit={limit}")
newsletters = get_newsletters(db, skip=skip, limit=limit)
return newsletters
@router.get("/newsletters/{newsletter_id}", response_model=Newsletter)
def read_newsletter(newsletter_id: int, db: Session = Depends(get_db)):
"""Retrieve a single newsletter by its ID."""
logger.info(f"Request to read newsletter with id={newsletter_id}")
db_newsletter = get_newsletter(db, newsletter_id=newsletter_id)
if db_newsletter is None:
logger.warning(f"Newsletter with id={newsletter_id} not found")
raise HTTPException(status_code=404, detail="Newsletter not found")
return db_newsletter
@router.put("/newsletters/{newsletter_id}", response_model=Newsletter)
def update_existing_newsletter(
newsletter_id: int, newsletter: NewsletterUpdate, db: Session = Depends(get_db)
):
"""Update an existing newsletter."""
logger.info(f"Request to update newsletter with id={newsletter_id}")
db_newsletter = update_newsletter(
db, newsletter_id=newsletter_id, newsletter_update=newsletter
)
if db_newsletter is None:
logger.warning(f"Newsletter with id={newsletter_id} not found, cannot update")
raise HTTPException(status_code=404, detail="Newsletter not found")
return db_newsletter
@router.delete("/newsletters/{newsletter_id}", response_model=Newsletter)
def delete_existing_newsletter(newsletter_id: int, db: Session = Depends(get_db)):
"""Delete a newsletter by its ID."""
logger.info(f"Request to delete newsletter with id={newsletter_id}")
db_newsletter = delete_newsletter(db, newsletter_id=newsletter_id)
if db_newsletter is None:
logger.warning(f"Newsletter with id={newsletter_id} not found, cannot delete")
raise HTTPException(status_code=404, detail="Newsletter not found")
return db_newsletter