From bf10149cb1826a39098255c272b9a2cb07b6f607 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Thu, 6 Aug 2026 11:05:52 +0700 Subject: [PATCH] fix(wheelofnames): center spoiler winner with nbsp padding instead of leading dots --- internal/modules/misc/handlers_test.go | 2 +- internal/modules/misc/wheelofnames_command.go | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/internal/modules/misc/handlers_test.go b/internal/modules/misc/handlers_test.go index e69a142..2daf81e 100644 --- a/internal/modules/misc/handlers_test.go +++ b/internal/modules/misc/handlers_test.go @@ -168,7 +168,7 @@ func TestWheelOfNames_ResultCaptionTruncatesLongResult(t *testing.T) { func TestWheelOfNames_ResultCaptionPadsShortWinnerToLongestOption(t *testing.T) { options := []string{"Bob", "Alexandria"} got := wheelResultCaption(options, 0) - want := `Result: .......Bob` + want := `Result: ` + strings.Repeat(wheelCaptionPad, 3) + "Bob" + strings.Repeat(wheelCaptionPad, 4) + `` if got != want { t.Fatalf("wheelResultCaption() = %q, want %q", got, want) } diff --git a/internal/modules/misc/wheelofnames_command.go b/internal/modules/misc/wheelofnames_command.go index f49f166..e1f488d 100644 --- a/internal/modules/misc/wheelofnames_command.go +++ b/internal/modules/misc/wheelofnames_command.go @@ -67,21 +67,27 @@ func wheelOfNamesCommand() modules.Command { const wheelUsage = "Usage: /wheelofnames " func wheelResultCaption(options []string, winner int) string { - result := truncateWheelResultCaption(options[winner]) - padding := wheelCaptionPadding(options, len([]rune(result))) - return `Result: ` + html.EscapeString(padding+result) + `` + result := padWheelResultCaption(options, truncateWheelResultCaption(options[winner])) + return `Result: ` + html.EscapeString(result) + `` } -// wheelCaptionPadding returns leading dots so every option renders a -// spoiler of equal length; otherwise the spoiler width reveals the winner. -func wheelCaptionPadding(options []string, resultRunes int) string { - longest := resultRunes +// Non-breaking space: regular spaces at the caption edges get trimmed by +// Telegram, which would shrink the spoiler and reveal the winner's length. +const wheelCaptionPad = "\u00a0" + +// padWheelResultCaption centers shorter winners with blank padding so every +// option renders a spoiler of equal length; otherwise the spoiler width +// reveals the winner. The longest option is returned unpadded. +func padWheelResultCaption(options []string, result string) string { + longest := len([]rune(result)) for _, option := range options { if n := len([]rune(truncateWheelResultCaption(option))); n > longest { longest = n } } - return strings.Repeat(".", longest-resultRunes) + missing := longest - len([]rune(result)) + left := missing / 2 + return strings.Repeat(wheelCaptionPad, left) + result + strings.Repeat(wheelCaptionPad, missing-left) } func truncateWheelResultCaption(result string) string {