diff --git a/core/scripts/webpanel/routers/api/v1/config/__init__.py b/core/scripts/webpanel/routers/api/v1/config/__init__.py index 02812a3..ee15be7 100644 --- a/core/scripts/webpanel/routers/api/v1/config/__init__.py +++ b/core/scripts/webpanel/routers/api/v1/config/__init__.py @@ -6,6 +6,7 @@ from . import normalsub from . import singbox from . import ip from . import misc +from . import extra_config router = APIRouter() @@ -16,4 +17,5 @@ router.include_router(telegram.router, prefix='/telegram') router.include_router(normalsub.router, prefix='/normalsub') router.include_router(singbox.router, prefix='/singbox') router.include_router(ip.router, prefix='/ip') +router.include_router(extra_config.router, prefix='/extra-config', tags=['Config - Extra Config']) router.include_router(misc.router) diff --git a/core/scripts/webpanel/routers/api/v1/config/extra_config.py b/core/scripts/webpanel/routers/api/v1/config/extra_config.py new file mode 100644 index 0000000..50605bc --- /dev/null +++ b/core/scripts/webpanel/routers/api/v1/config/extra_config.py @@ -0,0 +1,59 @@ +from fastapi import APIRouter, HTTPException +from ..schema.response import DetailResponse +import json +from ..schema.config.extra_config import ( + AddExtraConfigBody, + DeleteExtraConfigBody, + ExtraConfigListResponse, +) +import cli_api + +router = APIRouter() + +@router.get('/list', response_model=ExtraConfigListResponse, summary='Get All Extra Configs') +async def get_all_extra_configs(): + """ + Retrieves the list of all configured extra proxy configurations. + + Returns: + A list of extra config objects, each containing a name and a URI. + """ + try: + configs_str = cli_api.list_extra_configs() + if not configs_str: + return [] + return json.loads(configs_str) + except json.JSONDecodeError as e: + raise HTTPException(status_code=500, detail=f"Failed to parse extra configs list: {e}") + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to retrieve extra configs: {str(e)}") + + +@router.post('/add', response_model=DetailResponse, summary='Add Extra Config') +async def add_extra_config(body: AddExtraConfigBody): + """ + Adds a new extra proxy configuration. + + Args: + body: Request body containing the name and URI of the config. + """ + try: + cli_api.add_extra_config(body.name, body.uri) + return DetailResponse(detail=f"Extra config '{body.name}' added successfully.") + except Exception as e: + raise HTTPException(status_code=400, detail=str(e)) + + +@router.post('/delete', response_model=DetailResponse, summary='Delete Extra Config') +async def delete_extra_config(body: DeleteExtraConfigBody): + """ + Deletes an extra proxy configuration by its name. + + Args: + body: Request body containing the name of the config to delete. + """ + try: + cli_api.delete_extra_config(body.name) + return DetailResponse(detail=f"Extra config '{body.name}' deleted successfully.") + except Exception as e: + raise HTTPException(status_code=400, detail=str(e)) \ No newline at end of file diff --git a/core/scripts/webpanel/routers/api/v1/schema/config/__init__.py b/core/scripts/webpanel/routers/api/v1/schema/config/__init__.py index cd54453..0aac258 100644 --- a/core/scripts/webpanel/routers/api/v1/schema/config/__init__.py +++ b/core/scripts/webpanel/routers/api/v1/schema/config/__init__.py @@ -3,3 +3,4 @@ from . import normalsub from . import singbox from . import telegram from . import warp +from . import extra_config diff --git a/core/scripts/webpanel/routers/api/v1/schema/config/extra_config.py b/core/scripts/webpanel/routers/api/v1/schema/config/extra_config.py new file mode 100644 index 0000000..fda8190 --- /dev/null +++ b/core/scripts/webpanel/routers/api/v1/schema/config/extra_config.py @@ -0,0 +1,24 @@ +from pydantic import BaseModel, field_validator, Field + +VALID_PROTOCOLS = ("vmess://", "vless://", "ss://", "trojan://") + +class ExtraConfigBase(BaseModel): + name: str = Field(..., min_length=1, description="A unique name for the configuration.") + uri: str = Field(..., description="The proxy URI.") + + @field_validator('uri') + def validate_uri_protocol(cls, v): + if not any(v.startswith(protocol) for protocol in VALID_PROTOCOLS): + raise ValueError(f"Invalid URI. Must start with one of {', '.join(VALID_PROTOCOLS)}") + return v + +class AddExtraConfigBody(ExtraConfigBase): + pass + +class DeleteExtraConfigBody(BaseModel): + name: str + +class ExtraConfigResponse(ExtraConfigBase): + pass + +ExtraConfigListResponse = list[ExtraConfigResponse] \ No newline at end of file