
- FastAPI application that monitors websites for updates - SQLite database with Website and WebsiteAlert models - REST API endpoints for website management and alerts - Background scheduler for automatic periodic checks - Content hashing to detect website changes - Health check endpoint and comprehensive documentation - Alembic migrations for database schema management - CORS middleware for cross-origin requests - Environment variable configuration support Co-Authored-By: Claude <noreply@anthropic.com>
80 lines
3.2 KiB
Python
80 lines
3.2 KiB
Python
from typing import List
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from app.db.session import get_db
|
|
from app.models.website import Website, WebsiteAlert
|
|
from app.api.schemas import WebsiteCreate, WebsiteUpdate, WebsiteResponse, AlertResponse
|
|
|
|
router = APIRouter(prefix="/websites", tags=["websites"])
|
|
|
|
@router.post("/", response_model=WebsiteResponse)
|
|
def create_website(website: WebsiteCreate, db: Session = Depends(get_db)):
|
|
db_website = db.query(Website).filter(Website.url == str(website.url)).first()
|
|
if db_website:
|
|
raise HTTPException(status_code=400, detail="Website URL already registered")
|
|
|
|
db_website = Website(
|
|
url=str(website.url),
|
|
name=website.name,
|
|
check_interval_minutes=website.check_interval_minutes
|
|
)
|
|
db.add(db_website)
|
|
db.commit()
|
|
db.refresh(db_website)
|
|
return db_website
|
|
|
|
@router.get("/", response_model=List[WebsiteResponse])
|
|
def list_websites(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
|
|
websites = db.query(Website).offset(skip).limit(limit).all()
|
|
return websites
|
|
|
|
@router.get("/{website_id}", response_model=WebsiteResponse)
|
|
def get_website(website_id: int, db: Session = Depends(get_db)):
|
|
website = db.query(Website).filter(Website.id == website_id).first()
|
|
if website is None:
|
|
raise HTTPException(status_code=404, detail="Website not found")
|
|
return website
|
|
|
|
@router.put("/{website_id}", response_model=WebsiteResponse)
|
|
def update_website(website_id: int, website_update: WebsiteUpdate, db: Session = Depends(get_db)):
|
|
website = db.query(Website).filter(Website.id == website_id).first()
|
|
if website is None:
|
|
raise HTTPException(status_code=404, detail="Website not found")
|
|
|
|
update_data = website_update.model_dump(exclude_unset=True)
|
|
for field, value in update_data.items():
|
|
setattr(website, field, value)
|
|
|
|
db.commit()
|
|
db.refresh(website)
|
|
return website
|
|
|
|
@router.delete("/{website_id}")
|
|
def delete_website(website_id: int, db: Session = Depends(get_db)):
|
|
website = db.query(Website).filter(Website.id == website_id).first()
|
|
if website is None:
|
|
raise HTTPException(status_code=404, detail="Website not found")
|
|
|
|
db.delete(website)
|
|
db.commit()
|
|
return {"message": "Website deleted successfully"}
|
|
|
|
@router.post("/{website_id}/check")
|
|
def check_website_now(website_id: int, db: Session = Depends(get_db)):
|
|
from app.services.website_checker import check_website_for_updates
|
|
|
|
website = db.query(Website).filter(Website.id == website_id).first()
|
|
if website is None:
|
|
raise HTTPException(status_code=404, detail="Website not found")
|
|
|
|
result = check_website_for_updates(website, db)
|
|
return {"message": "Website check completed", "has_changes": result}
|
|
|
|
@router.get("/{website_id}/alerts", response_model=List[AlertResponse])
|
|
def get_website_alerts(website_id: int, db: Session = Depends(get_db)):
|
|
website = db.query(Website).filter(Website.id == website_id).first()
|
|
if website is None:
|
|
raise HTTPException(status_code=404, detail="Website not found")
|
|
|
|
alerts = db.query(WebsiteAlert).filter(WebsiteAlert.website_id == website_id).order_by(WebsiteAlert.detected_at.desc()).all()
|
|
return alerts |