feat(geodata): add standard source presets (#6504)

* feat(geodata): add standard source presets

Expose the existing geofile allowlist to the Geodata editor so administrators can configure the supported scheduled downloads without copying URLs manually

Tested with npm run test, npm run lint, npm run typecheck, npm run format:check, and go test ./internal/web/service ./internal/web/controller -run '^(TestStandardGeodataSources|TestGeodata)' -count=1

Assisted-by: OpenCode:openai/gpt-5.6-terra (mostly)

* fix(geodata): preserve custom source entries

Add missing standard sources instead of replacing existing custom entries.

Assisted-by: OpenCode:openai/gpt-5.6-terra (mostly)
This commit is contained in:
ilyusha
2026-09-13 21:02:43 +03:00
committed by GitHub
parent ff1a6c3caf
commit d600de2c2e
19 changed files with 148 additions and 2 deletions
+16
View File
@@ -2200,6 +2200,22 @@ var geofileAllowlist = map[string]geofileEntry{
"geosite_RU.dat": {"https://github.com/runetfreedom/russia-v2ray-rules-dat", "geosite.dat", "geosite_RU.dat"},
}
// GeodataSource identifies a file Xray downloads through its geodata configuration.
type GeodataSource struct {
URL string `json:"url"`
File string `json:"file"`
}
// StandardGeodataSources derives the panel presets from the geofile update allowlist.
func StandardGeodataSources() []GeodataSource {
sources := make([]GeodataSource, 0, len(geofileAllowlist))
for _, entry := range geofileAllowlist {
sources = append(sources, GeodataSource{URL: entry.latestURL(), File: entry.FileName})
}
slices.SortFunc(sources, func(a, b GeodataSource) int { return strings.Compare(a.File, b.File) })
return sources
}
func (entry geofileEntry) latestURL() string {
return entry.Repo + "/releases/latest/download/" + entry.Asset
}
@@ -392,3 +392,24 @@ func TestUpdateGeofileRejectsNameOutsideAllowlist(t *testing.T) {
t.Fatalf("error = %q, want it to name the allowlist", err)
}
}
func TestStandardGeodataSources(t *testing.T) {
want := []GeodataSource{
{URL: "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", File: "geoip.dat"},
{URL: "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", File: "geoip_IR.dat"},
{URL: "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", File: "geoip_RU.dat"},
{URL: "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", File: "geosite.dat"},
{URL: "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", File: "geosite_IR.dat"},
{URL: "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", File: "geosite_RU.dat"},
}
got := StandardGeodataSources()
if len(got) != len(want) {
t.Fatalf("sources = %d entries, want %d", len(got), len(want))
}
for i := range want {
if got[i] != want[i] {
t.Errorf("source %d = %+v, want %+v", i, got[i], want[i])
}
}
}