mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-16 00:01:02 +00:00
fix(sub): drop empty remark segments instead of leaving a stray separator
expandSegment dropped a "|" segment only when its tokens rendered the unlimited mark, so a segment whose only token resolved to the empty string (a client with no comment, an unlimited client's expiry date) was kept as bare decoration, leaving a trailing "|" or a dangling emoji on every share link's remark. Drop a token-bearing segment whenever none of its tokens produce a real value, while still keeping pure-literal segments.
This commit is contained in:
@@ -124,23 +124,23 @@ func expandRemarkVars(template string, ctx remarkContext) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expandSegment expands one "|" segment and reports whether it should be dropped.
|
// expandSegment expands one "|" segment and reports whether it should be dropped.
|
||||||
// It drops only when the segment carries an unlimited (∞) quota/expiry token and
|
// A segment that contains tokens is dropped when none of them resolve to a real
|
||||||
// no other token in it resolves to a non-empty value — so a segment mixing, say,
|
// value — whether because they render the unlimited (∞) mark or the empty string
|
||||||
// {{EMAIL}} with {{TRAFFIC_LEFT}} is always kept.
|
// — so it leaves no stray "|" separator or dangling decoration. A segment mixing,
|
||||||
|
// say, {{EMAIL}} with {{TRAFFIC_LEFT}} is kept, and a pure-literal segment (no
|
||||||
|
// tokens) is always kept.
|
||||||
func expandSegment(seg string, ctx remarkContext) (string, bool) {
|
func expandSegment(seg string, ctx remarkContext) (string, bool) {
|
||||||
hasUnlimited, hasOtherValue := false, false
|
hasToken, hasOtherValue := false, false
|
||||||
out := remarkVarRe.ReplaceAllStringFunc(seg, func(m string) string {
|
out := remarkVarRe.ReplaceAllStringFunc(seg, func(m string) string {
|
||||||
|
hasToken = true
|
||||||
token := m[2 : len(m)-2]
|
token := m[2 : len(m)-2]
|
||||||
val := remarkVarValue(token, ctx)
|
val := remarkVarValue(token, ctx)
|
||||||
switch {
|
if val != "" && !(unlimitedDropTokens[token] && val == unlimitedMark) {
|
||||||
case unlimitedDropTokens[token] && val == unlimitedMark:
|
|
||||||
hasUnlimited = true
|
|
||||||
case val != "":
|
|
||||||
hasOtherValue = true
|
hasOtherValue = true
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
})
|
})
|
||||||
return out, hasUnlimited && !hasOtherValue
|
return out, hasToken && !hasOtherValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func remarkVarValue(token string, ctx remarkContext) string {
|
func remarkVarValue(token string, ctx remarkContext) string {
|
||||||
|
|||||||
@@ -128,6 +128,23 @@ func TestExpandRemarkVars_DropUnlimitedSegments(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExpandRemarkVars_DropEmptySegments(t *testing.T) {
|
||||||
|
inbound := &model.Inbound{Remark: "host"}
|
||||||
|
|
||||||
|
// A client with no comment: the {{COMMENT}} segment resolves to empty and
|
||||||
|
// must be dropped, not left as a trailing "|".
|
||||||
|
noComment := expandCtx(model.Client{}, xray.ClientTraffic{Enable: true}, inbound)
|
||||||
|
if got := expandRemarkVars("{{INBOUND}}|{{COMMENT}}", noComment); got != "host" {
|
||||||
|
t.Errorf("empty comment segment = %q, want %q (no trailing pipe)", got, "host")
|
||||||
|
}
|
||||||
|
|
||||||
|
// A decorated empty segment (emoji + empty token) drops whole, not leaving
|
||||||
|
// a dangling emoji.
|
||||||
|
if got := expandRemarkVars("{{INBOUND}}|📅{{EXPIRE_DATE}}", noComment); got != "host" {
|
||||||
|
t.Errorf("decorated empty segment = %q, want %q", got, "host")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClientStatus(t *testing.T) {
|
func TestClientStatus(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user