diff --git a/internal/telegram/handlers_post.go b/internal/telegram/handlers_post.go index 5820a72..2f78945 100644 --- a/internal/telegram/handlers_post.go +++ b/internal/telegram/handlers_post.go @@ -453,56 +453,10 @@ func (b *Bot) handleConfirmCallback(c tele.Context, userID int64, action string) return c.Respond(&tele.CallbackResponse{Text: "添加成功"}) } -// sendMessageCopy 复制消息内容发送(非转发,可编辑) +// sendMessageCopy 复制消息内容发送(使用 copyMessage API 保留原格式) func (b *Bot) sendMessageCopy(to *tele.Chat, msg *tele.Message) (*tele.Message, error) { - // 图片 - if msg.Photo != nil { - photo := &tele.Photo{File: msg.Photo.File, Caption: msg.Caption} - return b.bot.Send(to, photo, tele.ModeHTML) - } - - // 视频 - if msg.Video != nil { - video := &tele.Video{File: msg.Video.File, Caption: msg.Caption} - return b.bot.Send(to, video, tele.ModeHTML) - } - - // 文档 - if msg.Document != nil { - doc := &tele.Document{File: msg.Document.File, Caption: msg.Caption} - return b.bot.Send(to, doc, tele.ModeHTML) - } - - // 音频 - if msg.Audio != nil { - audio := &tele.Audio{File: msg.Audio.File, Caption: msg.Caption} - return b.bot.Send(to, audio, tele.ModeHTML) - } - - // 语音 - if msg.Voice != nil { - voice := &tele.Voice{File: msg.Voice.File} - return b.bot.Send(to, voice) - } - - // 贴纸 - if msg.Sticker != nil { - sticker := &tele.Sticker{File: msg.Sticker.File} - return b.bot.Send(to, sticker) - } - - // 动图 - if msg.Animation != nil { - anim := &tele.Animation{File: msg.Animation.File, Caption: msg.Caption} - return b.bot.Send(to, anim, tele.ModeHTML) - } - - // 纯文本 - if msg.Text != "" { - return b.bot.Send(to, msg.Text, tele.ModeHTML, tele.NoPreview) - } - - return nil, fmt.Errorf("不支持的消息类型") + // 使用 Copy 方法,完整保留原消息的 entities(代码块、粗体、斜体等格式) + return b.bot.Copy(to, msg) } // sendAlbumCopy 复制相册发送到频道,返回第一条消息 @@ -511,30 +465,14 @@ func (b *Bot) sendAlbumCopy(to *tele.Chat, msgs []*tele.Message) (*tele.Message, return nil, fmt.Errorf("相册为空") } - var album tele.Album + // 转换为 Editable 接口切片 + editables := make([]tele.Editable, len(msgs)) for i, msg := range msgs { - var caption string - if i == 0 { - // 只有第一条消息带 caption - caption = msg.Caption - } - - if msg.Photo != nil { - album = append(album, &tele.Photo{File: msg.Photo.File, Caption: caption}) - } else if msg.Video != nil { - album = append(album, &tele.Video{File: msg.Video.File, Caption: caption}) - } else if msg.Document != nil { - album = append(album, &tele.Document{File: msg.Document.File, Caption: caption}) - } else if msg.Audio != nil { - album = append(album, &tele.Audio{File: msg.Audio.File, Caption: caption}) - } + editables[i] = msg } - if len(album) == 0 { - return nil, fmt.Errorf("相册中没有支持的媒体类型") - } - - sentMsgs, err := b.bot.SendAlbum(to, album, tele.ModeHTML) + // 使用 CopyMany 保留原格式(代码块、粗体等 entities) + sentMsgs, err := b.bot.CopyMany(to, editables) if err != nil { return nil, err } diff --git a/internal/toc/manager.go b/internal/toc/manager.go index 29bcdea..9e22a3a 100644 --- a/internal/toc/manager.go +++ b/internal/toc/manager.go @@ -81,7 +81,7 @@ func (m *Manager) updateMessage(content string) error { // 纯文本模式 if msgID == 0 { - msg, err := m.bot.Send(chat, content, tele.ModeMarkdown, tele.NoPreview) + msg, err := m.bot.Send(chat, content, tele.ModeHTML, tele.NoPreview) if err != nil { return err } @@ -93,7 +93,7 @@ func (m *Manager) updateMessage(content string) error { Chat: chat, } - _, err = m.bot.Edit(existingMsg, content, tele.ModeMarkdown, tele.NoPreview) + _, err = m.bot.Edit(existingMsg, content, tele.ModeHTML, tele.NoPreview) if err != nil { errMsg := err.Error() // 内容未变化,忽略 @@ -101,7 +101,7 @@ func (m *Manager) updateMessage(content string) error { return nil } if strings.Contains(errMsg, "message to edit not found") { - msg, err := m.bot.Send(chat, content, tele.ModeMarkdown, tele.NoPreview) + msg, err := m.bot.Send(chat, content, tele.ModeHTML, tele.NoPreview) if err != nil { return err } @@ -120,7 +120,7 @@ func (m *Manager) updateWithPhoto(chat *tele.Chat, msgID int, content string) er } if msgID == 0 { - msg, err := m.bot.Send(chat, photo, tele.ModeMarkdown) + msg, err := m.bot.Send(chat, photo, tele.ModeHTML) if err != nil { return err } @@ -133,7 +133,7 @@ func (m *Manager) updateWithPhoto(chat *tele.Chat, msgID int, content string) er } // 编辑图片消息的 caption - _, err := m.bot.EditCaption(existingMsg, content, tele.ModeMarkdown) + _, err := m.bot.EditCaption(existingMsg, content, tele.ModeHTML) if err != nil { errMsg := err.Error() if err == tele.ErrMessageNotModified || strings.Contains(errMsg, "message is not modified") { @@ -142,7 +142,7 @@ func (m *Manager) updateWithPhoto(chat *tele.Chat, msgID int, content string) er // 旧消息不是图片或找不到,重新发送 if strings.Contains(errMsg, "message to edit not found") || strings.Contains(errMsg, "no caption") { - msg, err := m.bot.Send(chat, photo, tele.ModeMarkdown) + msg, err := m.bot.Send(chat, photo, tele.ModeHTML) if err != nil { return err } diff --git a/internal/toc/renderer.go b/internal/toc/renderer.go index b7afdc4..62a374f 100644 --- a/internal/toc/renderer.go +++ b/internal/toc/renderer.go @@ -2,6 +2,7 @@ package toc import ( "fmt" + "html" "strings" ) @@ -17,28 +18,28 @@ func (m *Manager) Render() (string, error) { } var sb strings.Builder - sb.WriteString("📚 **频道目录**\n") + sb.WriteString("📚 频道目录\n") sb.WriteString("━━━━━━━━━━━━━━━\n\n") if len(categories) == 0 { - sb.WriteString("_暂无分类_") + sb.WriteString("暂无分类") return sb.String(), nil } for _, cat := range categories { entries := entriesByCategory[cat.Name] - sb.WriteString(fmt.Sprintf("📁 **%s**", cat.Name)) + sb.WriteString(fmt.Sprintf("📁 %s", html.EscapeString(cat.Name))) if len(entries) > 0 { sb.WriteString(fmt.Sprintf(" (%d)", len(entries))) } sb.WriteString("\n") if len(entries) == 0 { - sb.WriteString(" _暂无内容_\n") + sb.WriteString(" 暂无内容\n") } else { for _, entry := range entries { - sb.WriteString(fmt.Sprintf(" • [%s](%s)\n", escapeMarkdown(entry.Title), entry.Link)) + sb.WriteString(fmt.Sprintf(" • %s\n", entry.Link, html.EscapeString(entry.Title))) } } sb.WriteString("\n") @@ -48,16 +49,3 @@ func (m *Manager) Render() (string, error) { return sb.String(), nil } - -func escapeMarkdown(s string) string { - replacer := strings.NewReplacer( - "[", "\\[", - "]", "\\]", - "(", "\\(", - ")", "\\)", - "*", "\\*", - "_", "\\_", - "`", "\\`", - ) - return replacer.Replace(s) -}