fix(sub): show {{EMAIL}} on first sub-body link only

The remark template's {{EMAIL}}/{{USERNAME}} were repeated on every link
of a subscription. Strip them from subsequent body links like the usage
tokens, so the email appears once on the first link. Display/QR remarks
and the other client tokens are unaffected.
This commit is contained in:
MHSanaei
2026-06-27 12:42:12 +02:00
parent 1bad2fcba1
commit 876d55f274
2 changed files with 39 additions and 1 deletions
+10 -1
View File
@@ -484,6 +484,15 @@ var connectionTokens = map[string]bool{
var displayRemoveTokens = mergeTokenSets(usageInfoTokens, connectionTokens) var displayRemoveTokens = mergeTokenSets(usageInfoTokens, connectionTokens)
// firstLinkOnlyBodyTokens are stripped from every subscription-body link after a
// client's first one: the usage/info tokens plus the per-client EMAIL/USERNAME
// identity. A client app needs the email once, so repeating it on every link of
// the same subscription is noise — show it on the first link only, like traffic.
var firstLinkOnlyBodyTokens = mergeTokenSets(usageInfoTokens, map[string]bool{
"EMAIL": true,
"USERNAME": true,
})
func mergeTokenSets(sets ...map[string]bool) map[string]bool { func mergeTokenSets(sets ...map[string]bool) map[string]bool {
out := make(map[string]bool) out := make(map[string]bool)
for _, set := range sets { for _, set := range sets {
@@ -554,7 +563,7 @@ func (s *SubService) effectiveTemplate(email string) string {
s.usageShown = map[string]bool{} s.usageShown = map[string]bool{}
} }
if s.usageShown[email] { if s.usageShown[email] {
return filterRemarkTemplate(translated, usageInfoTokens) return filterRemarkTemplate(translated, firstLinkOnlyBodyTokens)
} }
s.usageShown[email] = true s.usageShown[email] = true
return translated return translated
+29
View File
@@ -610,3 +610,32 @@ func TestUsageOnFirstLinkOnly_SingleBracket(t *testing.T) {
t.Fatalf("second link must not carry usage: %q", second) t.Fatalf("second link must not carry usage: %q", second)
} }
} }
func TestEmailOnFirstLinkOnly(t *testing.T) {
s := &SubService{
remarkTemplate: "{{INBOUND}} {{EMAIL}}|📊{{TRAFFIC_LEFT}}",
subscriptionBody: true,
usageShown: map[string]bool{},
}
inbound := &model.Inbound{
Remark: "DE",
ClientStats: []xray.ClientTraffic{{
Email: "alice@x",
Enable: true,
Total: 100 * gb,
}},
}
client := model.Client{Email: "alice@x"}
first := s.genTemplatedRemark(inbound, client, "", "ws")
s.usageShown["alice@x"] = true
second := s.genTemplatedRemark(inbound, client, "", "ws")
if !strings.Contains(first, "alice@x") {
t.Fatalf("first link should carry email: %q", first)
}
if strings.Contains(second, "alice@x") {
t.Fatalf("second link must not carry email: %q", second)
}
if !strings.Contains(second, "DE") {
t.Fatalf("second link should still carry the inbound name: %q", second)
}
}