127 lines
3.7 KiB
Python
127 lines
3.7 KiB
Python
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from proxy_pool.common.dependencies import get_db, get_registry
|
|
from proxy_pool.plugins.registry import PluginRegistry
|
|
from proxy_pool.proxy.models import ProxySource
|
|
from proxy_pool.proxy.schemas import (
|
|
ProxySourceCreate,
|
|
ProxySourceResponse,
|
|
ProxySourceUpdate,
|
|
)
|
|
|
|
router = APIRouter(prefix="/sources", tags=["sources"])
|
|
|
|
|
|
@router.get("", response_model=list[ProxySourceResponse])
|
|
async def list_sources(
|
|
is_active: bool | None = None,
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> list[ProxySourceResponse]:
|
|
query = select(ProxySource)
|
|
if is_active is not None:
|
|
query = query.where(ProxySource.is_active == is_active)
|
|
query = query.order_by(ProxySource.created_at.desc())
|
|
|
|
result = await db.execute(query)
|
|
sources = result.scalars().all()
|
|
return [ProxySourceResponse.model_validate(s) for s in sources]
|
|
|
|
|
|
@router.post(
|
|
"",
|
|
response_model=ProxySourceResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def create_source(
|
|
body: ProxySourceCreate,
|
|
db: AsyncSession = Depends(get_db),
|
|
registry: PluginRegistry = Depends(get_registry),
|
|
) -> ProxySourceResponse:
|
|
# Validate parser exists
|
|
try:
|
|
registry.get_parser(body.parser_name)
|
|
except Exception:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
detail=f"No parser registered with name '{body.parser_name}'",
|
|
) from None
|
|
|
|
source = ProxySource(
|
|
url=body.url,
|
|
parser_name=body.parser_name,
|
|
cron_schedule=body.cron_schedule,
|
|
default_protocol=body.default_protocol,
|
|
)
|
|
db.add(source)
|
|
await db.commit()
|
|
await db.refresh(source)
|
|
|
|
return ProxySourceResponse.model_validate(source)
|
|
|
|
|
|
@router.get("/{source_id}", response_model=ProxySourceResponse)
|
|
async def get_source(
|
|
source_id: UUID,
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> ProxySourceResponse:
|
|
source = await db.get(ProxySource, source_id)
|
|
if source is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Source not found",
|
|
)
|
|
return ProxySourceResponse.model_validate(source)
|
|
|
|
|
|
@router.patch("/{source_id}", response_model=ProxySourceResponse)
|
|
async def update_source(
|
|
source_id: UUID,
|
|
body: ProxySourceUpdate,
|
|
db: AsyncSession = Depends(get_db),
|
|
registry: PluginRegistry = Depends(get_registry),
|
|
) -> ProxySourceResponse:
|
|
source = await db.get(ProxySource, source_id)
|
|
if source is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Source not found",
|
|
)
|
|
|
|
update_data = body.model_dump(exclude_unset=True)
|
|
|
|
if "parser_name" in update_data:
|
|
try:
|
|
registry.get_parser(update_data["parser_name"])
|
|
except Exception:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
detail=f"No parser registered with name '{update_data['parser_name']}'",
|
|
) from None
|
|
|
|
for field, value in update_data.items():
|
|
setattr(source, field, value)
|
|
|
|
await db.commit()
|
|
await db.refresh(source)
|
|
|
|
return ProxySourceResponse.model_validate(source)
|
|
|
|
|
|
@router.delete("/{source_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_source(
|
|
source_id: UUID,
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> None:
|
|
source = await db.get(ProxySource, source_id)
|
|
if source is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Source not found",
|
|
)
|
|
await db.delete(source)
|
|
await db.commit()
|