212 lines
4.9 KiB
Go
212 lines
4.9 KiB
Go
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)
|
|
}
|