Small fixes and a bit of refactoring.

This commit is contained in:
Andrey Parhomenko 2023-09-30 09:55:45 +03:00
parent b39e63cbaa
commit 37cd1d37fd
8 changed files with 56 additions and 227 deletions

View file

@ -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").

View file

@ -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 {
}

View file

@ -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,7 +147,7 @@ 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)
@ -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
}
}
*/

View file

@ -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

View file

@ -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
}
}*/

View file

@ -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)
}

View file

@ -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 {

8
tg/poll.go Normal file
View file

@ -0,0 +1,8 @@
package tg
type Poll struct {
}
type PollCompo struct {
}