diff --git a/discord.go b/discord.go index 384aa68..739890f 100644 --- a/discord.go +++ b/discord.go @@ -398,11 +398,7 @@ func (b *Bot) cmdInventoryList(s *discordgo.Session, i *discordgo.InteractionCre b.replyEphemeral(s, i, "Keine Lagerbestände gefunden.") return } - var lines []string - for _, it := range items { - lines = append(lines, fmt.Sprintf("#%d — %s Q%d: %s %s%s%s", it.ID, it.Name, it.Quality, formatAmount(it.QuantityAmount), it.QuantityUnit, locationSuffix(it.Location), noteSuffix(it.Note))) - } - b.replyEphemeral(s, i, strings.Join(lines, "\n")) + b.replyEphemeral(s, i, "Internes Lager\n"+inventoryTable(items)) } func (b *Bot) cmdInventoryCheck(s *discordgo.Session, i *discordgo.InteractionCreate) { @@ -657,6 +653,69 @@ func noteSuffix(v string) string { } return " — " + strings.TrimSpace(v) } + +func inventoryTable(items []InventoryItem) string { + const maxMessageLen = 1900 + + var b strings.Builder + b.WriteString("```text\n") + b.WriteString(fmt.Sprintf("%-4s %-22s %-5s %-10s %-8s %-24s\n", "ID", "Ware", "Q", "Menge", "Einheit", "Ort")) + b.WriteString(strings.Repeat("-", 78)) + b.WriteString("\n") + + shown := 0 + for _, it := range items { + name := truncateText(it.Name, 22) + location := truncateText(strings.TrimSpace(it.Location), 24) + if location == "" { + location = "-" + } + + row := fmt.Sprintf( + "%-4d %-22s %-5d %-10s %-8s %-24s\n", + it.ID, + name, + it.Quality, + formatAmount(it.QuantityAmount), + it.QuantityUnit, + location, + ) + if strings.TrimSpace(it.Note) != "" { + row += fmt.Sprintf(" Notiz: %s\n", truncateText(it.Note, 70)) + } + + // Discord-Nachrichten sind auf 2000 Zeichen begrenzt. Bei langen Listen + // brechen wir sauber ab und schließen den Codeblock trotzdem korrekt. + remainingHint := fmt.Sprintf("… plus %d weitere Positionen\n", len(items)-shown) + if b.Len()+len(row)+len(remainingHint)+len("```") > maxMessageLen { + if len(items)-shown > 0 { + b.WriteString(remainingHint) + } + break + } + + b.WriteString(row) + shown++ + } + + b.WriteString("```") + return b.String() +} + +func truncateText(v string, max int) string { + v = strings.TrimSpace(v) + if max <= 0 { + return "" + } + runes := []rune(v) + if len(runes) <= max { + return v + } + if max == 1 { + return string(runes[:1]) + } + return string(runes[:max-1]) + "…" +} func safeThreadName(v string) string { v = strings.Map(func(r rune) rune { if strings.ContainsRune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", r) {