package telegram import ( "fmt" "strings" "tgchanbot/internal/storage" tele "gopkg.in/telebot.v3" ) const ( cbPrefixCat = "cat:" cbPrefixConfirm = "confirm:" cbCancel = "cancel" ) func (b *Bot) handlePost(c tele.Context) error { b.states.StartPost(c.Sender().ID) return c.Reply("📨 请转发一条来自目标频道的消息") } func (b *Bot) handleTextOrForwarded(c tele.Context) error { msg := c.Message() if msg == nil || msg.OriginalChat == nil { return nil } return b.handleForwarded(c) } func (b *Bot) handleForwarded(c tele.Context) error { if !b.cfg.IsAdmin(c.Sender().ID) { return nil } state := b.states.Get(c.Sender().ID) if state == nil || state.Step != StepAwaitForward { return nil } msg := c.Message() if msg.OriginalChat == nil { return c.Reply("❌ 这不是一条转发消息,请转发频道消息") } b.states.SetForwarded(c.Sender().ID, msg) categories, err := b.storage.ListCategories() if err != nil { b.states.Delete(c.Sender().ID) return c.Reply(fmt.Sprintf("❌ 获取分类失败: %v", err)) } if len(categories) == 0 { b.states.Delete(c.Sender().ID) return c.Reply("❌ 暂无分类,请先使用 /cat_add 创建分类") } keyboard := b.buildCategoryKeyboard(categories) return c.Reply("📁 请选择分类:", keyboard) } func (b *Bot) buildCategoryKeyboard(categories []storage.Category) *tele.ReplyMarkup { menu := &tele.ReplyMarkup{} var rows []tele.Row var currentRow []tele.Btn for _, cat := range categories { btn := menu.Data(cat.Name, cbPrefixCat+cat.Name) currentRow = append(currentRow, btn) if len(currentRow) == 3 { rows = append(rows, menu.Row(currentRow...)) currentRow = nil } } if len(currentRow) > 0 { rows = append(rows, menu.Row(currentRow...)) } cancelBtn := menu.Data("❌ 取消", cbCancel) rows = append(rows, menu.Row(cancelBtn)) menu.Inline(rows...) return menu } func (b *Bot) handleCallback(c tele.Context) error { if !b.cfg.IsAdmin(c.Sender().ID) { return c.Respond(&tele.CallbackResponse{Text: "无权限"}) } data := c.Callback().Data userID := c.Sender().ID switch { case data == cbCancel: return b.handleCancelCallback(c, userID) case strings.HasPrefix(data, cbPrefixCat): category := strings.TrimPrefix(data, cbPrefixCat) return b.handleCategoryCallback(c, userID, category) case strings.HasPrefix(data, cbPrefixConfirm): action := strings.TrimPrefix(data, cbPrefixConfirm) return b.handleConfirmCallback(c, userID, action) } return c.Respond() } func (b *Bot) handleCancelCallback(c tele.Context, userID int64) error { b.states.Delete(userID) c.Edit("❌ 已取消") return c.Respond(&tele.CallbackResponse{Text: "已取消"}) } func (b *Bot) handleCategoryCallback(c tele.Context, userID int64, category string) error { state := b.states.Get(userID) if state == nil || state.Step != StepAwaitCategory { return c.Respond(&tele.CallbackResponse{Text: "会话已过期"}) } b.states.SetCategory(userID, category) channelName := "未知频道" if state.ForwardedMsg.OriginalChat != nil { channelName = state.ForwardedMsg.OriginalChat.Title } menu := &tele.ReplyMarkup{} confirmBtn := menu.Data("✅ 确认", cbPrefixConfirm+"yes") cancelBtn := menu.Data("❌ 取消", cbCancel) menu.Inline(menu.Row(confirmBtn, cancelBtn)) text := fmt.Sprintf("📋 确认添加?\n\n频道: %s\n分类: %s", channelName, category) c.Edit(text, menu) return c.Respond() } func (b *Bot) handleConfirmCallback(c tele.Context, userID int64, action string) error { if action != "yes" { return b.handleCancelCallback(c, userID) } state := b.states.Get(userID) if state == nil || state.Step != StepAwaitConfirm { return c.Respond(&tele.CallbackResponse{Text: "会话已过期"}) } defer b.states.Delete(userID) msg := state.ForwardedMsg title := extractTitle(msg) link := buildMessageLink(msg) entry, err := b.storage.CreateEntry(state.SelectedCat, title, link) if err != nil { c.Edit(fmt.Sprintf("❌ 保存失败: %v", err)) return c.Respond(&tele.CallbackResponse{Text: "保存失败"}) } b.toc.TriggerUpdate() text := fmt.Sprintf("✅ 已添加\n\nID: %s\n分类: %s\n标题: %s", entry.ID, entry.Category, entry.Title) c.Edit(text) return c.Respond(&tele.CallbackResponse{Text: "添加成功"}) } func extractTitle(msg *tele.Message) string { text := msg.Text if text == "" { text = msg.Caption } lines := strings.Split(text, "\n") title := strings.TrimSpace(lines[0]) if len(title) > 50 { title = title[:47] + "..." } if title == "" { title = "无标题" } return title } func buildMessageLink(msg *tele.Message) string { if msg.OriginalChat == nil { return "" } chat := msg.OriginalChat msgID := msg.OriginalMessageID if msgID == 0 { msgID = msg.ID } if chat.Username != "" { return fmt.Sprintf("https://t.me/%s/%d", chat.Username, msgID) } chatID := chat.ID if chatID < 0 { chatID = -chatID - 1000000000000 } return fmt.Sprintf("https://t.me/c/%d/%d", chatID, msgID) }