mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-09 21:00:58 +00:00
feat(sub): allow identity tokens on every subscription link (#5935)
Keep usage tokens first-link-only while adding an opt-in setting for repeating EMAIL and USERNAME in subscription-body remarks. Co-authored-by: x06579 <x06579@ai-dashboard>
This commit is contained in:
@@ -560,7 +560,11 @@ func (s *SubService) effectiveTemplate(email string) string {
|
||||
s.usageShown = map[string]bool{}
|
||||
}
|
||||
if s.usageShown[email] {
|
||||
return filterRemarkTemplate(translated, firstLinkOnlyBodyTokens)
|
||||
remove := firstLinkOnlyBodyTokens
|
||||
if s.showIdentityOnAllLinks {
|
||||
remove = usageInfoTokens
|
||||
}
|
||||
return filterRemarkTemplate(translated, remove)
|
||||
}
|
||||
s.usageShown[email] = true
|
||||
return translated
|
||||
|
||||
@@ -652,3 +652,40 @@ func TestEmailOnFirstLinkOnly(t *testing.T) {
|
||||
t.Fatalf("second link should still carry the inbound name: %q", second)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentityOnAllLinks(t *testing.T) {
|
||||
const template = "{{INBOUND}}-{{EMAIL}}|{{USERNAME}}|📊{{TRAFFIC_LEFT}}|{{STATUS_EMOJI}}"
|
||||
inbound := &model.Inbound{
|
||||
Remark: "DE",
|
||||
ClientStats: []xray.ClientTraffic{{
|
||||
Email: "alice@x",
|
||||
Enable: true,
|
||||
Total: 100 * gb,
|
||||
Up: 20 * gb,
|
||||
}},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
enabled bool
|
||||
wantSecond string
|
||||
}{
|
||||
{name: "disabled", wantSecond: "DE"},
|
||||
{name: "enabled", enabled: true, wantSecond: "DE-alice@x|alice@x"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &SubService{
|
||||
remarkTemplate: template,
|
||||
subscriptionBody: true,
|
||||
showIdentityOnAllLinks: tt.enabled,
|
||||
}
|
||||
client := model.Client{Email: "alice@x"}
|
||||
if got := s.genTemplatedRemark(inbound, client, "", "ws"); got != "DE-alice@x|alice@x|📊80.00GB|✅" {
|
||||
t.Fatalf("first link = %q", got)
|
||||
}
|
||||
if got := s.genTemplatedRemark(inbound, client, "", "ws"); got != tt.wantSecond {
|
||||
t.Fatalf("second link = %q, want %q", got, tt.wantSecond)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +40,10 @@ type SubService struct {
|
||||
// usageShown tracks, per client email, whether the info part of the template
|
||||
// has already been emitted this request, so it appears on the first body
|
||||
// link only. Per-request state; reset in PrepareForRequest.
|
||||
usageShown map[string]bool
|
||||
inboundService service.InboundService
|
||||
settingService service.SettingService
|
||||
usageShown map[string]bool
|
||||
showIdentityOnAllLinks bool
|
||||
inboundService service.InboundService
|
||||
settingService service.SettingService
|
||||
// nodesByID is populated per request from the Node table so
|
||||
// resolveInboundAddress can return the node's address for any
|
||||
// inbound whose NodeID is set. Keeps the per-link host derivation
|
||||
@@ -197,6 +198,10 @@ func (s *SubService) loadRemarkSettings() {
|
||||
if err != nil {
|
||||
s.datepicker = "gregorian"
|
||||
}
|
||||
s.showIdentityOnAllLinks, err = s.settingService.GetSubShowIdentityOnAllLinks()
|
||||
if err != nil {
|
||||
s.showIdentityOnAllLinks = false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SubService) configuredPublicHost() string {
|
||||
|
||||
Reference in New Issue
Block a user