mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-15 17:16:07 +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.
|
||||
// It drops only when the segment carries an unlimited (∞) quota/expiry token and
|
||||
// no other token in it resolves to a non-empty value — so a segment mixing, say,
|
||||
// {{EMAIL}} with {{TRAFFIC_LEFT}} is always kept.
|
||||
// A segment that contains tokens is dropped when none of them resolve to a real
|
||||
// value — whether because they render the unlimited (∞) mark or the empty string
|
||||
// — 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) {
|
||||
hasUnlimited, hasOtherValue := false, false
|
||||
hasToken, hasOtherValue := false, false
|
||||
out := remarkVarRe.ReplaceAllStringFunc(seg, func(m string) string {
|
||||
hasToken = true
|
||||
token := m[2 : len(m)-2]
|
||||
val := remarkVarValue(token, ctx)
|
||||
switch {
|
||||
case unlimitedDropTokens[token] && val == unlimitedMark:
|
||||
hasUnlimited = true
|
||||
case val != "":
|
||||
if val != "" && !(unlimitedDropTokens[token] && val == unlimitedMark) {
|
||||
hasOtherValue = true
|
||||
}
|
||||
return val
|
||||
})
|
||||
return out, hasUnlimited && !hasOtherValue
|
||||
return out, hasToken && !hasOtherValue
|
||||
}
|
||||
|
||||
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) {
|
||||
cases := []struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user