feat: add webpanel API for extra subscription configs

This commit is contained in:
Whispering Wind
2025-08-17 15:39:20 +03:30
committed by GitHub
parent 491b384468
commit 68dde4f863
4 changed files with 86 additions and 0 deletions

View File

@ -6,6 +6,7 @@ from . import normalsub
from . import singbox from . import singbox
from . import ip from . import ip
from . import misc from . import misc
from . import extra_config
router = APIRouter() router = APIRouter()
@ -16,4 +17,5 @@ router.include_router(telegram.router, prefix='/telegram')
router.include_router(normalsub.router, prefix='/normalsub') router.include_router(normalsub.router, prefix='/normalsub')
router.include_router(singbox.router, prefix='/singbox') router.include_router(singbox.router, prefix='/singbox')
router.include_router(ip.router, prefix='/ip') 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) router.include_router(misc.router)

View File

@ -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))

View File

@ -3,3 +3,4 @@ from . import normalsub
from . import singbox from . import singbox
from . import telegram from . import telegram
from . import warp from . import warp
from . import extra_config

View File

@ -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]