chore(telegram): rebuild telegram module with go-telegram/bot
fix(telegram): fix bot cannot send message in groups
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user