feat(xray): autocomplete geosite/geoip categories in the routing rule editor

Writing a routing rule today means remembering exact geosite:/geoip:/
ext:file:code syntax by hand, with no way to discover what categories
actually exist in the .dat files sitting in the bin folder -- including
custom ones like geosite_roscom.dat added via the Geodata auto-update
feature. The Domain/IP fields in the rule editor now suggest categories
as you type (e.g. "you" -> "geosite:youtube"), built live from whatever
.dat files are actually on disk, while still accepting any free-typed
value exactly as before.

Backend: GET /panel/api/xray/getGeodataCategories scans the bin folder,
parses matched geosite*/geoip*.dat files via xray-core's own exported
protobuf types, and formats each category as the exact rule syntax
xray-core's parser accepts -- geosite:/geoip: for the default files,
ext:<file>:<code> for anything else (there's no shorthand for custom
files). Cached in memory keyed by each file's (name, size, modTime) so
a request-time scan is cheap until a file actually changes.

Frontend: the Domain/IP inputs become Select "tags" fields fed by a new
useGeodataCategories() query hook, with an explicit substring filter so
"you" matches "geosite:youtube" (not a prefix). The array<->CSV-string
adapter lives entirely at the FormField transform boundary, so the
underlying form schema and saved rule shape are unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kuzz007
2026-07-26 17:13:07 +03:00
parent c282c17b5a
commit 2736f9beb3
13 changed files with 692 additions and 2 deletions
+10
View File
@@ -41,6 +41,7 @@ func (a *XraySettingController) initRouter(g *gin.RouterGroup) {
g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig)
g.GET("/getOutboundsTraffic", a.getOutboundsTraffic)
g.GET("/getXrayResult", a.getXrayResult)
g.GET("/getGeodataCategories", a.getGeodataCategories)
g.POST("/", a.getXraySetting)
g.POST("/warp/:action", a.warp)
@@ -168,6 +169,15 @@ func (a *XraySettingController) getXrayResult(c *gin.Context) {
jsonObj(c, a.XrayService.GetXrayResult(), nil)
}
// getGeodataCategories returns every geosite/geoip category found in the
// .dat files currently present in the Xray bin folder (including any custom
// files the admin added via the Geodata auto-update feature), formatted as
// ready-to-use routing-rule suggestion strings for the routing rule editor's
// Domain/IP autocomplete.
func (a *XraySettingController) getGeodataCategories(c *gin.Context) {
jsonObj(c, a.XraySettingService.GetGeodataCategories(), nil)
}
// warp handles Warp-related operations based on the action parameter.
func (a *XraySettingController) warp(c *gin.Context) {
action := c.Param("action")