Small fixes and a bit of refactoring.
This commit is contained in:
parent
b39e63cbaa
commit
37cd1d37fd
8 changed files with 56 additions and 227 deletions
|
@ -112,6 +112,14 @@ WithInitFunc(func(c *tg.Context) {
|
||||||
tg.NewButton("Send location").Go("/send-location"),
|
tg.NewButton("Send location").Go("/send-location"),
|
||||||
).Reply(),
|
).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{
|
return tg.UI{
|
||||||
kbd,
|
kbd,
|
||||||
tg.NewMessage("").Reply(
|
tg.NewMessage("Use the reply keyboard to get back").Reply(
|
||||||
backKeyboard.Reply(),
|
backKeyboard.Reply(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -242,7 +250,9 @@ WithInitFunc(func(c *tg.Context) {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)).WithRoot(tg.NewCommandCompo().
|
)).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 ")
|
c.Sendf("Please, use /start ")
|
||||||
})).WithCommands(
|
})).WithCommands(
|
||||||
tg.NewCommand("info").
|
tg.NewCommand("info").
|
||||||
|
|
47
tg/beh.go
47
tg/beh.go
|
@ -77,50 +77,3 @@ func (beh *Behaviour) GetScreen(pth Path) *Screen {
|
||||||
return 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 {
|
|
||||||
}
|
|
||||||
|
|
63
tg/bot.go
63
tg/bot.go
|
@ -22,12 +22,12 @@ type Bot struct {
|
||||||
// Private bot behaviour.
|
// Private bot behaviour.
|
||||||
behaviour *Behaviour
|
behaviour *Behaviour
|
||||||
// Group bot behaviour.
|
// Group bot behaviour.
|
||||||
groupBehaviour *GroupBehaviour
|
//groupBehaviour *GroupBehaviour
|
||||||
// Bot behaviour in channels.
|
// Bot behaviour in channels.
|
||||||
channelBehaviour *ChannelBehaviour
|
//channelBehaviour *ChannelBehaviour
|
||||||
contexts map[SessionId] *context
|
contexts map[SessionId] *context
|
||||||
sessions SessionMap
|
sessions SessionMap
|
||||||
groupSessions GroupSessionMap
|
//groupSessions GroupSessionMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the new bot with empty sessions and behaviour.
|
// 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)
|
return c.Bot.Send(c.Session.Id, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func (bot *Bot) Render(
|
// Get session by its ID. Can be used for any scope
|
||||||
sid SessionId, r Renderable,
|
// including private, group and channel.
|
||||||
) (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
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func (bot *Bot) GetSession(
|
func (bot *Bot) GetSession(
|
||||||
sid SessionId,
|
sid SessionId,
|
||||||
) (*Session, bool) {
|
) (*Session, bool) {
|
||||||
|
@ -94,13 +74,6 @@ func (bot *Bot) GetSession(
|
||||||
return session, ok
|
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 {
|
func (b *Bot) WithBehaviour(beh *Behaviour) *Bot {
|
||||||
b.behaviour = beh
|
b.behaviour = beh
|
||||||
b.sessions = make(SessionMap)
|
b.sessions = make(SessionMap)
|
||||||
|
@ -112,7 +85,7 @@ func (b *Bot) WithSessions(sessions SessionMap) *Bot {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot {
|
/*func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot {
|
||||||
b.groupBehaviour = beh
|
b.groupBehaviour = beh
|
||||||
b.groupSessions = make(GroupSessionMap)
|
b.groupSessions = make(GroupSessionMap)
|
||||||
return b
|
return b
|
||||||
|
@ -121,12 +94,18 @@ func (b *Bot) WithGroupBehaviour(beh *GroupBehaviour) *Bot {
|
||||||
func (b *Bot) WithGroupSessions(sessions GroupSessionMap) *Bot {
|
func (b *Bot) WithGroupSessions(sessions GroupSessionMap) *Bot {
|
||||||
b.groupSessions = sessions
|
b.groupSessions = sessions
|
||||||
return b
|
return b
|
||||||
|
}*/
|
||||||
|
|
||||||
|
func (bot *Bot) DeleteCommands() {
|
||||||
|
//tgbotapi.NewBotCommandScopeAllPrivateChats(),
|
||||||
|
cfg := tgbotapi.NewDeleteMyCommands()
|
||||||
|
bot.Api.Request(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting the command on the user side.
|
// Setting the command on the user side.
|
||||||
func (bot *Bot) SetCommands(
|
func (bot *Bot) SetCommands(
|
||||||
scope tgbotapi.BotCommandScope,
|
scope tgbotapi.BotCommandScope,
|
||||||
cmdMap map[CommandName] BotCommander,
|
cmdMap CommandMap,
|
||||||
) {
|
) {
|
||||||
// First the private commands.
|
// First the private commands.
|
||||||
names := []string{}
|
names := []string{}
|
||||||
|
@ -135,7 +114,7 @@ func (bot *Bot) SetCommands(
|
||||||
}
|
}
|
||||||
sort.Strings([]string(names))
|
sort.Strings([]string(names))
|
||||||
|
|
||||||
cmds := []BotCommander{}
|
cmds := []*Command{}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
cmds = append(
|
cmds = append(
|
||||||
cmds,
|
cmds,
|
||||||
|
@ -159,8 +138,7 @@ func (bot *Bot) SetCommands(
|
||||||
|
|
||||||
// Run the bot with the Behaviour.
|
// Run the bot with the Behaviour.
|
||||||
func (bot *Bot) Run() error {
|
func (bot *Bot) Run() error {
|
||||||
if bot.behaviour == nil &&
|
if bot.behaviour == nil {
|
||||||
bot.groupBehaviour == nil {
|
|
||||||
return errors.New("no behaviour defined")
|
return errors.New("no behaviour defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,9 +147,9 @@ func (bot *Bot) Run() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
uc := tgbotapi.NewUpdate(0)
|
uc := tgbotapi.NewUpdate(0)
|
||||||
uc.Timeout = 60
|
uc.Timeout = 10
|
||||||
updates := bot.Api.GetUpdatesChan(uc)
|
updates := bot.Api.GetUpdatesChan(uc)
|
||||||
handles := make(map[string]chan *Update)
|
handles := make(map[string] chan *Update)
|
||||||
|
|
||||||
if bot.behaviour != nil {
|
if bot.behaviour != nil {
|
||||||
chn := make(chan *Update)
|
chn := make(chan *Update)
|
||||||
|
@ -179,7 +157,7 @@ func (bot *Bot) Run() error {
|
||||||
go bot.handlePrivate(chn)
|
go bot.handlePrivate(chn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if bot.groupBehaviour != nil {
|
/*if bot.groupBehaviour != nil {
|
||||||
commanders := make(map[CommandName] BotCommander)
|
commanders := make(map[CommandName] BotCommander)
|
||||||
for k, v := range bot.groupBehaviour.Commands {
|
for k, v := range bot.groupBehaviour.Commands {
|
||||||
commanders[k] = v
|
commanders[k] = v
|
||||||
|
@ -192,7 +170,7 @@ func (bot *Bot) Run() error {
|
||||||
handles["group"] = chn
|
handles["group"] = chn
|
||||||
handles["supergroup"] = chn
|
handles["supergroup"] = chn
|
||||||
go bot.handleGroup(chn)
|
go bot.handleGroup(chn)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
me, _ := bot.Api.GetMe()
|
me, _ := bot.Api.GetMe()
|
||||||
bot.Me = &me
|
bot.Me = &me
|
||||||
|
@ -249,7 +227,7 @@ func (bot *Bot) handlePrivate(updates chan *Update) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
func (bot *Bot) handleGroup(updates chan *Update) {
|
func (bot *Bot) handleGroup(updates chan *Update) {
|
||||||
var sid SessionId
|
var sid SessionId
|
||||||
chans := make(map[SessionId]chan *Update)
|
chans := make(map[SessionId]chan *Update)
|
||||||
|
@ -273,3 +251,4 @@ func (bot *Bot) handleGroup(updates chan *Update) {
|
||||||
chn <- u
|
chn <- u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -6,14 +6,18 @@ import (
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BotCommander interface {
|
type CommandType uint8
|
||||||
ToApi() tgbotapi.BotCommand
|
const (
|
||||||
}
|
PrivateCommandType CommandType = iota
|
||||||
type Message = tgbotapi.Message
|
GroupCommandType
|
||||||
|
ChannelCommandType
|
||||||
|
)
|
||||||
|
|
||||||
type CommandName string
|
type CommandName string
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Name CommandName
|
Name CommandName
|
||||||
|
Type CommandType
|
||||||
Description string
|
Description string
|
||||||
Action Action
|
Action Action
|
||||||
Widget Widget
|
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
|
// The type is used to recognize commands and execute
|
||||||
// its actions and widgets .
|
// its actions and widgets .
|
||||||
type CommandCompo struct {
|
type CommandCompo struct {
|
||||||
|
@ -165,13 +134,14 @@ func (widget *CommandCompo) Filter(
|
||||||
|
|
||||||
// Implementing server.
|
// Implementing server.
|
||||||
func (compo *CommandCompo) Serve(c *Context) {
|
func (compo *CommandCompo) Serve(c *Context) {
|
||||||
commanders := make(map[CommandName] BotCommander)
|
/*commanders := make(map[CommandName] BotCommander)
|
||||||
for k, v := range compo.Commands {
|
for k, v := range compo.Commands {
|
||||||
commanders[k] = v
|
commanders[k] = v
|
||||||
}
|
}*/
|
||||||
|
c.Bot.DeleteCommands()
|
||||||
c.Bot.SetCommands(
|
c.Bot.SetCommands(
|
||||||
tgbotapi.NewBotCommandScopeAllPrivateChats(),
|
tgbotapi.NewBotCommandScopeAllPrivateChats(),
|
||||||
commanders,
|
compo.Commands,
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUpdates *UpdateChan
|
var cmdUpdates *UpdateChan
|
||||||
|
|
|
@ -32,6 +32,6 @@ func DefineAction(typeName string, a Action) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefineGroupAction(typ string, a GroupAction) error {
|
/*func DefineGroupAction(typ string, a GroupAction) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}*/
|
||||||
|
|
92
tg/group.go
92
tg/group.go
|
@ -1,94 +1,2 @@
|
||||||
package tg
|
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)
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package tg
|
||||||
import (
|
import (
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
type Message = tgbotapi.Message
|
||||||
|
|
||||||
// Simple text message type.
|
// Simple text message type.
|
||||||
type MessageCompo struct {
|
type MessageCompo struct {
|
||||||
|
|
8
tg/poll.go
Normal file
8
tg/poll.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package tg
|
||||||
|
|
||||||
|
type Poll struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type PollCompo struct {
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue