2025-04-04 15:20:01 +08:00

117 lines
4.1 KiB
Python

from typing import Annotated
from fastapi import APIRouter, UploadFile, Form, Query
from app.constants.api_result import ApiCode
from app.constants.domain import DomainStatus
from app.web.request.domain_request import AddDomainRequest, DeleteDomainRequest, UpdateDomainRequest, \
GetDomainListRequest, CrawlNowRequest, ToggleDomainRequest
from app.web.results import ApiResult
from app.web.service.domain_service import DomainService
router = APIRouter(prefix="/api/domain", tags=["域名管理"])
@router.get("/v1/list")
def get_all_domains(request: Annotated[GetDomainListRequest, Query()]):
"""获取所有的域名信息,支持根据域名、状态进行搜索,不传则返回全部数据,支持分页"""
return DomainService.get_list(request.page, request.size, request.domain, request.status)
@router.post("/v1/add")
def add_domains(request: AddDomainRequest):
"""添加域名"""
# 检查是否有重复的
result = DomainService.get_by_domains(request.domains)
if not result.success:
return result
existed_domains = [item.domain for item in result.data]
new_domains = [x for x in request.domains if x not in existed_domains]
if not new_domains:
return ApiResult.ok(0)
# 添加并返回
return DomainService.add_domains(request.crawl_interval, request.crawl_now, new_domains)
@router.post("/v1/import")
def import_domains(
# 同时提交文件和参数的时候,没办法使用 FormModel 的形式,必须一个一个定义
file: UploadFile,
crawl_interval: int = Form(),
crawl_now: bool = Form(),
):
"""通过上传文件添加域名,如果单个文件很大,以后改成开新协程/线程处理"""
# 把文件内容读出来
domains = []
for line in file.file:
line = line.strip()
domains.append(line.decode("UTF-8"))
# 创建协程任务
# asyncio.create_task(DomainService.add_domains(crawl_interval, crawl_now, domains))
# 检查是否有重复域名
result = DomainService.get_by_domains(domains)
if not result.success:
return result
existed_domains = [item.domain for item in result.data]
new_domains = [x for x in domains if x not in existed_domains]
# 添加并返回
return DomainService.add_domains(crawl_interval, crawl_now, new_domains)
# noinspection DuplicatedCode
@router.post("/v1/update")
def update_domain(request: UpdateDomainRequest):
"""更新域名的数据,主要是采集间隔,支持批量修改,传入多个 id"""
# 检查待更新的域名是否存在
result = DomainService.get_by_ids(request.domain_ids)
if not result.success:
return result
existed_domain_ids = [item.id for item in result.data]
for domain_id in request.domain_ids:
if domain_id not in existed_domain_ids:
return ApiResult.error(ApiCode.PARAM_ERROR.value, f"域名 ID {domain_id} 不存在")
# 更新刷新时间
return DomainService.update_domain_interval(request.domain_ids, request.crawl_interval)
# noinspection DuplicatedCode
@router.post("/v1/delete")
def delete_domain(request: DeleteDomainRequest):
"""删除域名,支持批量删除,传入多个 id"""
# 检查待删除的域名是否存在
result = DomainService.get_by_ids(request.domain_ids)
if not result.success:
return result
existed_domain_ids = [item.id for item in result.data]
for domain_id in request.domain_ids:
if domain_id not in existed_domain_ids:
return ApiResult.error(ApiCode.PARAM_ERROR.value, f"域名 ID {domain_id} 不存在")
# 删除域名
return DomainService.delete_domains(request.domain_ids, request.remove_surl)
@router.post("/v1/crawl")
def crawl_now(request: CrawlNowRequest):
"""立即爬取,实际上是把 status 置为 2"""
result = DomainService.update_domain_status(request.domain_ids, DomainStatus.QUEUEING.value)
return result
@router.post("/v1/toggle")
def toggle_domain(request: ToggleDomainRequest):
"""暂停爬取某个域名"""
return DomainService.update_domain_status(request.domain_ids, DomainStatus.PAUSE.value)