diff --git a/cmd/test/main.go b/cmd/test/main.go index 6c751c3..d00177b 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -112,6 +112,14 @@ WithInitFunc(func(c *tg.Context) { tg.NewButton("Send location").Go("/send-location"), ).Reply(), ), + + tg.Func(func(c *tg.Context){ + for u := range c.Input() { + if u.EditedMessage != nil { + c.Sendf2("The new message is `%s`", u.EditedMessage.Text) + } + } + }), } }), @@ -208,7 +216,7 @@ WithInitFunc(func(c *tg.Context) { return tg.UI{ kbd, - tg.NewMessage("").Reply( + tg.NewMessage("Use the reply keyboard to get back").Reply( backKeyboard.Reply(), ), } @@ -242,7 +250,9 @@ WithInitFunc(func(c *tg.Context) { }), ), )).WithRoot(tg.NewCommandCompo(). -WithPreStart(tg.Func(func(c *tg.Context){ +WithUsage(tg.Func(func(c *tg.Context){ + c.Sendf("There is no such command %q", c.Message.Command()) +})).WithPreStart(tg.Func(func(c *tg.Context){ c.Sendf("Please, use /start ") })).WithCommands( tg.NewCommand("info"). diff --git a/tg/beh.go b/tg/beh.go index 92702f3..121a034 100644 --- a/tg/beh.go +++ b/tg/beh.go @@ -77,50 +77,3 @@ func (beh *Behaviour) GetScreen(pth Path) *Screen { return screen } -// The type describes behaviour for the bot in group chats. -type GroupBehaviour struct { - Init GroupAction - // List of commands - Commands GroupCommandMap -} - -// Returns new empty group behaviour object. -func NewGroupBehaviour() *GroupBehaviour { - return &GroupBehaviour{ - Commands: make(GroupCommandMap), - } -} - -// Sets an Action for initialization on each group connected to the -// group bot. -func (b *GroupBehaviour) WithInitAction(a GroupAction) *GroupBehaviour { - b.Init = a - return b -} - -// The method reciveies a function to be called on initialization of the -// bot group bot. -func (b *GroupBehaviour) InitFunc(fn GroupActionFunc) *GroupBehaviour { - return b.WithInitAction(fn) -} - -// The method sets group commands. -func (b *GroupBehaviour) WithCommands( - cmds ...*GroupCommand, -) *GroupBehaviour { - for _, cmd := range cmds { - if cmd.Name == "" { - panic("empty command name") - } - _, ok := b.Commands[cmd.Name] - if ok { - panic("duplicate command definition") - } - b.Commands[cmd.Name] = cmd - } - return b -} - -// The type describes behaviour for the bot in channels. -type ChannelBehaviour struct { -} diff --git a/tg/bot.go b/tg/bot.go index bd6f9ee..bda1a61 100644 --- a/tg/bot.go +++ b/tg/bot.go @@ -22,12 +22,12 @@ type Bot struct { // Private bot behaviour. behaviour *Behaviour // Group bot behaviour. - groupBehaviour *GroupBehaviour + //groupBehaviour *GroupBehaviour // Bot behaviour in channels. - channelBehaviour *ChannelBehaviour + //channelBehaviour *ChannelBehaviour contexts map[SessionId] *context sessions SessionMap - groupSessions GroupSessionMap + //groupSessions GroupSessionMap } // Return the new bot with empty sessions and behaviour. @@ -65,28 +65,8 @@ func (bot *Bot) Send( return c.Bot.Send(c.Session.Id, v) } -/*func (bot *Bot) Render( - sid SessionId, r Renderable, -) (MessageMap, error) { - configs := r.Render(sid, bot) - if configs == nil { - return nil, MapCollisionErr - } - messages := make(MessageMap) - for _, config := range configs { - _, collision := messages[config.Name] - if collision { - return messages, MapCollisionErr - } - msg, err := bot.Api.Send(config.ToApi()) - if err != nil { - return messages, err - } - messages[config.Name] = &msg - } - return messages, nil -}*/ - +// Get session by its ID. Can be used for any scope +// including private, group and channel. func (bot *Bot) GetSession( sid SessionId, ) (*Session, bool) { @@ -94,13 +74,6 @@ func (bot *Bot) GetSession( return session, ok } -func (bot *Bot) GetGroupSession( - sid SessionId, -) (*GroupSession, bool) { - session, ok := bot.groupSessions[sid] - return session, ok -} - func (b *Bot) WithBehaviour(beh *Behaviour) *Bot { b.behaviour = beh b.sessions = make(SessionMap) @@ -112,7 +85,7 @@ func (b *Bot) WithSessions(sessions SessionMap) *Bot { return b } -func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot { +/*func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot { b.groupBehaviour = beh b.groupSessions = make(GroupSessionMap) return b @@ -121,12 +94,18 @@ func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot { func (b *Bot) WithGroupSessions(sessions GroupSessionMap) *Bot { b.groupSessions = sessions return b +}*/ + +func (bot *Bot) DeleteCommands() { + //tgbotapi.NewBotCommandScopeAllPrivateChats(), + cfg := tgbotapi.NewDeleteMyCommands() + bot.Api.Request(cfg) } // Setting the command on the user side. func (bot *Bot) SetCommands( scope tgbotapi.BotCommandScope, - cmdMap map[CommandName] BotCommander, + cmdMap CommandMap, ) { // First the private commands. names := []string{} @@ -135,7 +114,7 @@ func (bot *Bot) SetCommands( } sort.Strings([]string(names)) - cmds := []BotCommander{} + cmds := []*Command{} for _, name := range names { cmds = append( cmds, @@ -159,8 +138,7 @@ func (bot *Bot) SetCommands( // Run the bot with the Behaviour. func (bot *Bot) Run() error { - if bot.behaviour == nil && - bot.groupBehaviour == nil { + if bot.behaviour == nil { return errors.New("no behaviour defined") } @@ -169,9 +147,9 @@ func (bot *Bot) Run() error { } uc := tgbotapi.NewUpdate(0) - uc.Timeout = 60 + uc.Timeout = 10 updates := bot.Api.GetUpdatesChan(uc) - handles := make(map[string]chan *Update) + handles := make(map[string] chan *Update) if bot.behaviour != nil { chn := make(chan *Update) @@ -179,7 +157,7 @@ func (bot *Bot) Run() error { go bot.handlePrivate(chn) } - if bot.groupBehaviour != nil { + /*if bot.groupBehaviour != nil { commanders := make(map[CommandName] BotCommander) for k, v := range bot.groupBehaviour.Commands { commanders[k] = v @@ -192,7 +170,7 @@ func (bot *Bot) Run() error { handles["group"] = chn handles["supergroup"] = chn go bot.handleGroup(chn) - } + }*/ me, _ := bot.Api.GetMe() bot.Me = &me @@ -249,7 +227,7 @@ func (bot *Bot) handlePrivate(updates chan *Update) { } } } - +/* func (bot *Bot) handleGroup(updates chan *Update) { var sid SessionId chans := make(map[SessionId]chan *Update) @@ -273,3 +251,4 @@ func (bot *Bot) handleGroup(updates chan *Update) { chn <- u } } +*/ diff --git a/tg/command.go b/tg/command.go index 97ce45a..41fe997 100644 --- a/tg/command.go +++ b/tg/command.go @@ -6,14 +6,18 @@ import ( tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) -type BotCommander interface { - ToApi() tgbotapi.BotCommand -} -type Message = tgbotapi.Message +type CommandType uint8 +const ( + PrivateCommandType CommandType = iota + GroupCommandType + ChannelCommandType +) + type CommandName string type Command struct { Name CommandName + Type CommandType Description string Action Action Widget Widget @@ -63,41 +67,6 @@ func (c *Command) Go(pth Path, args ...any) *Command { }) } -type GroupCommand struct { - Name CommandName - Description string - Action GroupAction -} -type GroupCommandMap map[CommandName]*GroupCommand - -func NewGroupCommand(name CommandName) *GroupCommand { - return &GroupCommand{ - Name: name, - } -} - -func (cmd *GroupCommand) WithAction(a GroupAction) *GroupCommand { - cmd.Action = a - return cmd -} - -func (cmd *GroupCommand) ActionFunc(fn GroupActionFunc) *GroupCommand { - return cmd.WithAction(fn) -} - - -func (cmd *GroupCommand) Desc(desc string) *GroupCommand { - cmd.Description = desc - return cmd -} - -func (c *GroupCommand) ToApi() tgbotapi.BotCommand { - ret := tgbotapi.BotCommand{} - ret.Command = string(c.Name) - ret.Description = c.Description - return ret -} - // The type is used to recognize commands and execute // its actions and widgets . type CommandCompo struct { @@ -165,13 +134,14 @@ func (widget *CommandCompo) Filter( // Implementing server. func (compo *CommandCompo) Serve(c *Context) { - commanders := make(map[CommandName] BotCommander) + /*commanders := make(map[CommandName] BotCommander) for k, v := range compo.Commands { commanders[k] = v - } + }*/ + c.Bot.DeleteCommands() c.Bot.SetCommands( tgbotapi.NewBotCommandScopeAllPrivateChats(), - commanders, + compo.Commands, ) var cmdUpdates *UpdateChan diff --git a/tg/encoding.go b/tg/encoding.go index 7a17e91..ab48df1 100644 --- a/tg/encoding.go +++ b/tg/encoding.go @@ -32,6 +32,6 @@ func DefineAction(typeName string, a Action) error { return nil } -func DefineGroupAction(typ string, a GroupAction) error { +/*func DefineGroupAction(typ string, a GroupAction) error { return nil -} +}*/ diff --git a/tg/group.go b/tg/group.go index f49b843..a1dbcb3 100644 --- a/tg/group.go +++ b/tg/group.go @@ -1,94 +1,2 @@ package tg -import ( - "fmt" - - //tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" -) - -// Customized actions for the group behaviour. -type GroupAction interface { - Act(*GroupContext) -} - -// The handler function type. -type GroupActionFunc func(*GroupContext) - -func (af GroupActionFunc) Act(a *GroupContext) { - af(a) -} - -type GC = GroupContext - -func (c *GroupContext) Session() *GroupSession { - session, _ := c.Bot.GetGroupSession( - SessionId(c.SentFrom().ID), - ) - return session -} - -type GroupContext struct { - *groupContext - *Update -} - -// Context for interaction inside groups. -type groupContext struct { - Session *GroupSession - Bot *Bot - updates chan *Update -} - -func (c *groupContext) run(a GroupAction, u *Update) { - go a.Act(&GroupContext{ - groupContext: c, - Update: u, - }) -} - -func (c *groupContext) handleUpdateChan(updates chan *Update) { - var act GroupAction - beh := c.Bot.groupBehaviour - for u := range updates { - if u.Message != nil { - msg := u.Message - if msg.IsCommand() { - cmdName := CommandName(msg.Command()) - - // Skipping the commands sent not to us. - withAt := msg.CommandWithAt() - if len(cmdName) == len(withAt) { - continue - } - - atName := withAt[len(cmdName)+1:] - if c.Bot.Me.UserName != atName { - continue - } - cmd, ok := beh.Commands[cmdName] - if !ok { - // Some lack of command handling - continue - } - act = cmd.Action - } - } - if act != nil { - c.run(act, u) - } - } -} - -func (c *groupContext) Sendf( - format string, - v ...any, -) (*Message, error) { - return c.Send(NewMessage( - fmt.Sprintf(format, v...), - )) -} - -// Sends into the chat specified values converted to strings. -func (c *groupContext) Send(v Sendable) (*Message, error) { - return c.Bot.Send(c.Session.Id, v) -} diff --git a/tg/message.go b/tg/message.go index 6fd15e0..3340634 100644 --- a/tg/message.go +++ b/tg/message.go @@ -3,6 +3,7 @@ package tg import ( tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) +type Message = tgbotapi.Message // Simple text message type. type MessageCompo struct { diff --git a/tg/poll.go b/tg/poll.go new file mode 100644 index 0000000..c7a6336 --- /dev/null +++ b/tg/poll.go @@ -0,0 +1,8 @@ +package tg + +type Poll struct { +} + +type PollCompo struct { +} +