from fastapi import FastAPI, HTTPException, Depends, Header from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Optional from sqlalchemy.orm import Session import uvicorn import os from dotenv import load_dotenv from database import get_db, create_tables, Item as ItemModel from schemas import ScrapeRequest, ScrapedPost from scraper import scrape_and_store from admin_sync import router as admin_sync_router # Load environment variables load_dotenv() # API Key for Django backend authentication API_KEY = os.getenv("ENGINE_API_KEY") app = FastAPI( title=os.getenv("FASTAPI_TITLE", "FastAPI ISS Project"), description=os.getenv("FASTAPI_DESCRIPTION", "A FastAPI project with Docker and PostgreSQL support"), version=os.getenv("FASTAPI_VERSION", "1.0.0") ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=eval(os.getenv("ALLOWED_ORIGINS", '["*"]')), allow_credentials=os.getenv("ALLOWED_CREDENTIALS", "true").lower() == "true", allow_methods=eval(os.getenv("ALLOWED_METHODS", '["*"]')), allow_headers=eval(os.getenv("ALLOWED_HEADERS", '["*"]')), ) # Pydantic models for basic items class ItemBase(BaseModel): name: str description: Optional[str] = None price: float class ItemCreate(ItemBase): pass class Item(ItemBase): id: int class Config: from_attributes = True @app.on_event("startup") async def startup_event(): create_tables() @app.get("/") async def root(): return {"message": "Welcome to FastAPI ISS Project!", "status": "running"} @app.get("/health") async def health_check(): return {"status": "healthy", "service": "FastAPI ISS"} @app.get("/items", response_model=List[Item]) async def get_items(db: Session = Depends(get_db)): items = db.query(ItemModel).all() return items @app.get("/items/{item_id}", response_model=Item) async def get_item(item_id: int, db: Session = Depends(get_db)): item = db.query(ItemModel).filter(ItemModel.id == item_id).first() if item is None: raise HTTPException(status_code=404, detail="Item not found") return item @app.post("/items", response_model=Item) async def create_item(item: ItemCreate, db: Session = Depends(get_db)): db_item = ItemModel(**item.dict()) db.add(db_item) db.commit() db.refresh(db_item) return db_item @app.put("/items/{item_id}", response_model=Item) async def update_item(item_id: int, item: ItemCreate, db: Session = Depends(get_db)): db_item = db.query(ItemModel).filter(ItemModel.id == item_id).first() if db_item is None: raise HTTPException(status_code=404, detail="Item not found") for key, value in item.dict().items(): setattr(db_item, key, value) db.commit() db.refresh(db_item) return db_item @app.delete("/items/{item_id}") async def delete_item(item_id: int, db: Session = Depends(get_db)): db_item = db.query(ItemModel).filter(ItemModel.id == item_id).first() if db_item is None: raise HTTPException(status_code=404, detail="Item not found") db.delete(db_item) db.commit() return {"message": "Item deleted successfully"} # Include admin router app.include_router(admin_sync_router) # ============================================================================ # Instagram Scraper Endpoint # ============================================================================ @app.post("/scrape/", response_model=List[ScrapedPost]) async def scrape_posts( request: ScrapeRequest, x_api_key: str = Header(...), db: Session = Depends(get_db) ): """Scrape Instagram posts for a given username""" if x_api_key != API_KEY: raise HTTPException(status_code=403, detail="Forbidden: Invalid API key") try: return scrape_and_store(db, request) except Exception as e: # Log the error for debugging print(f"❌ Scraping error for {request.username}: {e}") raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)