package tgbot import ( "context" "errors" "strconv" "strings" "sync" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) type CommandType int32 const ( CommandTypeUnknown CommandType = 0 CommandTypeCommand CommandType = 1 CommandTypeCallback CommandType = 2 ) type TgMessageList struct { lock sync.Mutex list []tgbotapi.Chattable } func (s *TgMessageList) Push(msg tgbotapi.Chattable) { s.lock.Lock() defer s.lock.Unlock() if s.list == nil { s.list = make([]tgbotapi.Chattable, 0) } s.list = append(s.list, msg) } func (s *TgMessageList) Pop() tgbotapi.Chattable { s.lock.Lock() defer s.lock.Unlock() var ret tgbotapi.Chattable if len(s.list) > 0 { ret = s.list[0] s.list = s.list[1:] } return ret } type TgCommands struct { commands map[string]*Command lock sync.Mutex } func (s *TgCommands) GetCommand(cmd string) *Command { s.lock.Lock() defer s.lock.Unlock() return s.commands[cmd] } func (s *TgCommands) SetCommand(cmd *Command) { s.lock.Lock() defer s.lock.Unlock() s.commands[cmd.Cmd] = cmd } type CommandFunc func(ctx context.Context, cmd *Command) error type Command struct { Cmd string // 命令 Help string // 命令帮助 Desc string // 命令描述 CmdType CommandType // 命令类型 Process CommandFunc // 处理函数 Params []string // 参数 botNames []string // @ skip bool // 是否跳过处理 owner *TgBot ParseMode string PhotoPath string FilePath string message *tgbotapi.Message } func (c *Command) Message() *tgbotapi.Message { return c.message } func (c *Command) HasFlag(flag string) bool { for _, arg := range c.Params { if strings.Contains(arg, "=") { ss := strings.Split(arg, "=") if len(ss) > 0 { if ss[0] == flag { return true } } } else { if arg == flag { return true } } } return false } func (c *Command) GetFlagStringValue(flag string) string { for index, arg := range c.Params { pos := strings.Index(arg, "=") if pos > 0 { cmd := arg[:pos] if cmd == flag { content := arg[pos+1:] if strings.HasPrefix(content, `"`) && strings.HasSuffix(content, `"`) { if text, err := strconv.Unquote(content); err != nil { return content } else { return text } } else { return content } } } else { if arg == flag { if index+1 < len(c.Params) { return c.Params[index+1] } } } } return "" } func (c *Command) GetFlagInt64Value(flag string) (int64, error) { s := c.GetFlagStringValue(flag) if s != "" { return strconv.ParseInt(s, 10, 64) } return 0, errors.New("flag value is empty") } func (c *Command) GetFlagInt32Value(flag string) (int32, error) { s := c.GetFlagStringValue(flag) if s != "" { i, err := strconv.ParseInt(s, 10, 64) return int32(i), err } return 0, errors.New("flag value is empty") } func (c *Command) GetFlagStringSlice(flag string) []string { s := c.GetFlagStringValue(flag) return strings.Split(s, ",") } func (c *Command) GetFlagInt64Slice(flag string) []int64 { ret := make([]int64, 0) s := c.GetFlagStringValue(flag) ss := strings.Split(s, ",") for _, v := range ss { if i, err := strconv.ParseInt(v, 10, 64); err == nil { ret = append(ret, i) } } return ret } func (c *Command) GetFlagInt32Slice(flag string) []int32 { ret := make([]int32, 0) s := c.GetFlagStringValue(flag) ss := strings.Split(s, ",") for _, v := range ss { if i, err := strconv.ParseInt(v, 10, 64); err == nil { ret = append(ret, int32(i)) } } return ret } func (c *Command) SendBack(text string) error { if c.message != nil { if c.CmdType == CommandTypeCallback { if c.PhotoPath != "" || c.FilePath != "" { return c.SendReply(text, nil) } else { return c.SendEdit(text, nil) } } else if c.CmdType == CommandTypeCommand { return c.SendReply(text, nil) } else { return c.SendText(text) } } else { return errors.New("tg message is nil") } } func (c *Command) SendEntity(ent *EntityList) error { if c == nil { return errors.New("bot cmd can not be nil") } if ent == nil { return errors.New("entity can not be nil") } if c.message == nil { return errors.New("tg message is nil") } chat := c.message.Chat.ID entities, text := ent.ToEntities() msg := tgbotapi.NewMessage(chat, text) msg.Entities = entities c.owner.messages.Push(msg) return nil } func (c *Command) SendReply(text string, replyMarkup interface{}) error { if c.message != nil { return replyMessage(c.owner, c.message, text, replyMarkup, c.ParseMode, c.PhotoPath, c.FilePath) } else { return errors.New("tg message is nil") } } func (c *Command) SendEdit(text string, replyMarkup interface{}) error { if c.message != nil { return editMessage(c.owner, c.message, text, replyMarkup, c.ParseMode) } else { return errors.New("tg message is nil") } } func (c *Command) SendText(text string) error { if c.message != nil { return sendMessageToChat(c.owner, text, c.message.Chat.ID, c.ParseMode, c.PhotoPath, c.FilePath) } else { return errors.New("tg message is nil") } } func (c *Command) SendFile(text string, fileName string) error { if c.message != nil { c.FilePath = fileName return sendMessageToChat(c.owner, text, c.message.Chat.ID, c.ParseMode, c.PhotoPath, c.FilePath) } else { return errors.New("tg message is nil") } } func (c *Command) SendDelete() error { if c.message != nil { msg := tgbotapi.NewDeleteMessage(c.message.Chat.ID, c.message.MessageID) _, err := c.owner.bot.Request(msg) return err } else { return errors.New("tg message is nil") } }