mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-08-21 08:26:41 +00:00
feat(portfolio): nest asset positions
This commit is contained in:
@@ -6,6 +6,7 @@ package chathelper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -15,6 +16,45 @@ import (
|
||||
"github.com/go-telegram/bot/models"
|
||||
)
|
||||
|
||||
// MonospaceTable renders an HTML-safe, left-aligned table for Telegram's
|
||||
// <pre> mode. Callers should send the result with ReplyHTML.
|
||||
func MonospaceTable(headers []string, rows [][]string) string {
|
||||
widths := make([]int, len(headers))
|
||||
for index, header := range headers {
|
||||
widths[index] = len([]rune(header))
|
||||
}
|
||||
for _, row := range rows {
|
||||
for index := range headers {
|
||||
if index < len(row) && len([]rune(row[index])) > widths[index] {
|
||||
widths[index] = len([]rune(row[index]))
|
||||
}
|
||||
}
|
||||
}
|
||||
var lines []string
|
||||
appendRow := func(row []string) {
|
||||
cells := make([]string, len(headers))
|
||||
for index := range headers {
|
||||
if index < len(row) {
|
||||
cells[index] = row[index]
|
||||
}
|
||||
if index < len(headers)-1 {
|
||||
cells[index] += strings.Repeat(" ", widths[index]-len([]rune(cells[index])))
|
||||
}
|
||||
}
|
||||
lines = append(lines, strings.Join(cells, " "))
|
||||
}
|
||||
appendRow(headers)
|
||||
separator := make([]string, len(headers))
|
||||
for index := range headers {
|
||||
separator[index] = strings.Repeat("-", widths[index])
|
||||
}
|
||||
appendRow(separator)
|
||||
for _, row := range rows {
|
||||
appendRow(row)
|
||||
}
|
||||
return "<pre>" + html.EscapeString(strings.Join(lines, "\n")) + "</pre>"
|
||||
}
|
||||
|
||||
// SubjectFor returns the identity key per-module state should be scoped by:
|
||||
// group/supergroup → chat ID (shared game state), otherwise → user ID.
|
||||
// Returns "" when no usable id is present (caller should reply with a
|
||||
|
||||
@@ -2,6 +2,7 @@ package chathelper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -268,3 +269,12 @@ func TestWinRate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonospaceTableAlignsAndEscapesHTML(t *testing.T) {
|
||||
got := MonospaceTable([]string{"Asset", "Qty"}, [][]string{{"<TCB>", "10"}, {"BTC", "2"}})
|
||||
for _, want := range []string{"<pre>", "Asset", "<TCB>", "BTC 2", "</pre>"} {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Fatalf("table missing %q in %q", want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user