chore(telegram): rebuild telegram module with go-telegram/bot

fix(telegram): fix bot cannot send message in groups
This commit is contained in:
2026-09-02 20:47:25 +08:00
parent 935ea24d54
commit 0b7fcd6c48
5 changed files with 185 additions and 322 deletions
@@ -0,0 +1,85 @@
package telegram
import (
"context"
"strings"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)
// maxMessageLen is the safe chunk size for outbound messages. Telegram's hard
// limit is 4096 characters; staying under it leaves headroom for encoding.
const maxMessageLen = 4000
// sendMessage sends a text message to a chat, splitting it into chunks that fit
// Telegram's 4096-character limit. All messages are sent with
// parse_mode=Markdown so fenced code blocks and inline formatting render as
// rich text. Templates must stay valid under Telegram's legacy Markdown:
// unpaired '*' or '_' characters (e.g. a lone '*Event: ...' label) make the
// API reject the whole message.
func (t *TelegramController) sendMessage(chatID int64, text string) error {
if t.client == nil {
return nil
}
if strings.TrimSpace(text) == "" {
return nil
}
for _, chunk := range splitMessage(text, maxMessageLen) {
if err := t.sendMessageChunk(chatID, chunk); err != nil {
return err
}
}
return nil
}
// sendMessageChunk issues a single sendMessage API call for one chunk.
func (t *TelegramController) sendMessageChunk(chatID int64, text string) error {
ctx, cancel := context.WithTimeout(context.Background(), apiTimeout)
defer cancel()
_, err := t.client.SendMessage(ctx, &bot.SendMessageParams{
ChatID: chatID,
Text: text,
ParseMode: models.ParseModeMarkdownV1, // Telegram legacy Markdown
})
return err
}
// splitMessage splits text into chunks of at most maxLen runes, keeping
// complete lines when possible.
func splitMessage(text string, maxLen int) []string {
if maxLen <= 0 {
return []string{text}
}
remaining := []rune(text)
if len(remaining) <= maxLen {
return []string{text}
}
var chunks []string
for len(remaining) > maxLen {
// Prefer the last newline within the window so messages aren't cut
// mid-line; fall back to a hard rune cut for overlong lines.
cut := maxLen
if nl := lastIndexRune(remaining[:maxLen], '\n'); nl > 0 {
cut = nl + 1
}
chunks = append(chunks, string(remaining[:cut]))
remaining = remaining[cut:]
}
if len(remaining) > 0 {
chunks = append(chunks, string(remaining))
}
return chunks
}
func lastIndexRune(s []rune, r rune) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == r {
return i
}
}
return -1
}