Release 3.9.0+3: subscription-URL routing, emoji flags, Remnawave provisioning.

Route credential-less http(s) URLs pasted into the add-link field to
subscription import (fixes remaining 'proxy URI missing username').
Extend geoflag with RU country names and city hints; live Remnawave
names already carrying emoji flags are kept as-is. Add admin
provisioning via configs/remnawave-api.json (GET by-username / POST
users, 50 GB MONTH plan) and the «Выдать доступ» UI panel.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Navis
2026-08-01 17:36:54 +03:00
co-authored by Cursor
parent e34312ef9c
commit 77bd7da861
24 changed files with 974 additions and 110 deletions
+44
View File
@@ -0,0 +1,44 @@
package linknorm
import (
"strings"
"testing"
)
func TestLooksLikeSubscriptionURL(t *testing.T) {
cases := []struct {
in string
want bool
}{
{"https://api.evilfox.win/ZKszcVcC3xbWb8qj", true},
{"http://panel.example.com/api/sub/abc", true},
{" https://api.evilfox.win/ZKszcVcC3xbWb8qj ", true},
{"https://user:pass@host:443", false}, // naive proxy link
{"https://user@host:443", false}, // has userinfo
{"quic://user:pass@host", false},
{"vless://uuid@host:443", false},
{"naive+https://user:pass@host:443", false},
{"not a url", false},
{"", false},
}
for _, c := range cases {
if got := LooksLikeSubscriptionURL(c.in); got != c.want {
t.Fatalf("%q: got %v want %v", c.in, got, c.want)
}
}
}
// Direct Normalize of a credential-less https URL must never surface the raw
// "proxy URI missing username" error — it explains this is a subscription URL.
func TestNormalizeSubscriptionURLError(t *testing.T) {
_, _, _, err := Normalize("", "https://api.evilfox.win/ZKszcVcC3xbWb8qj")
if err == nil {
t.Fatal("expected error")
}
if strings.Contains(err.Error(), "missing username") {
t.Fatalf("raw parser error leaked: %v", err)
}
if !strings.Contains(err.Error(), "подписк") {
t.Fatalf("error should mention subscription: %v", err)
}
}