Globlal refactoring. Less embedded structures making everything more clear.
This commit is contained in:
parent
522b9ada02
commit
9a1202d777
9 changed files with 216 additions and 178 deletions
|
@ -18,12 +18,12 @@ var (
|
||||||
|
|
||||||
incDecKeyboard = tg.NewKeyboard("").Row(
|
incDecKeyboard = tg.NewKeyboard("").Row(
|
||||||
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
||||||
d := c.V.(*UserData)
|
d := c.Session.Value.(*UserData)
|
||||||
d.Counter++
|
d.Counter++
|
||||||
c.Sendf("%d", d.Counter)
|
c.Sendf("%d", d.Counter)
|
||||||
}),
|
}),
|
||||||
tg.NewButton("-").ActionFunc(func(c *tg.Context) {
|
tg.NewButton("-").ActionFunc(func(c *tg.Context) {
|
||||||
d := c.SessionValue().(*UserData)
|
d := c.Session.Value.(*UserData)
|
||||||
d.Counter--
|
d.Counter--
|
||||||
c.Sendf("%d", d.Counter)
|
c.Sendf("%d", d.Counter)
|
||||||
}),
|
}),
|
||||||
|
@ -50,7 +50,7 @@ var (
|
||||||
var err error
|
var err error
|
||||||
if c.Message.Location != nil {
|
if c.Message.Location != nil {
|
||||||
l := c.Message.Location
|
l := c.Message.Location
|
||||||
err = c.Sendf(
|
_, err = c.Sendf(
|
||||||
"Longitude: %f\n"+
|
"Longitude: %f\n"+
|
||||||
"Latitude: %f\n"+
|
"Latitude: %f\n"+
|
||||||
"Heading: %d"+
|
"Heading: %d"+
|
||||||
|
@ -60,7 +60,7 @@ var (
|
||||||
l.Heading,
|
l.Heading,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
err = c.Send("Somehow wrong location was sent")
|
_, err = c.Send("Somehow wrong location was sent")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Send(err)
|
c.Send(err)
|
||||||
|
@ -79,7 +79,7 @@ var (
|
||||||
var beh = tg.NewBehaviour().
|
var beh = tg.NewBehaviour().
|
||||||
WithInitFunc(func(c *tg.Context) {
|
WithInitFunc(func(c *tg.Context) {
|
||||||
// The session initialization.
|
// The session initialization.
|
||||||
c.V = &UserData{}
|
c.Session.Value = &UserData{}
|
||||||
c.ChangeScreen("start")
|
c.ChangeScreen("start")
|
||||||
|
|
||||||
}).WithScreens(
|
}).WithScreens(
|
||||||
|
@ -109,7 +109,7 @@ var beh = tg.NewBehaviour().
|
||||||
WithKeyboard(incDecKeyboard).
|
WithKeyboard(incDecKeyboard).
|
||||||
// The function will be called when reaching the screen.
|
// The function will be called when reaching the screen.
|
||||||
ActionFunc(func(c *tg.Context) {
|
ActionFunc(func(c *tg.Context) {
|
||||||
d := c.V.(*UserData)
|
d := c.Session.Value.(*UserData)
|
||||||
c.Sendf("Current counter value = %d", d.Counter)
|
c.Sendf("Current counter value = %d", d.Counter)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ var beh = tg.NewBehaviour().
|
||||||
tg.NewButton("Check").
|
tg.NewButton("Check").
|
||||||
WithData("check").
|
WithData("check").
|
||||||
ActionFunc(func(a *tg.Context) {
|
ActionFunc(func(a *tg.Context) {
|
||||||
d := a.V.(*UserData)
|
d := a.Session.Value.(*UserData)
|
||||||
a.Sendf("Counter = %d", d.Counter)
|
a.Sendf("Counter = %d", d.Counter)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -170,7 +170,7 @@ func mutateMessage(fn func(string) string) tg.ActionFunc {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.Sendf("%s", fn(msg))
|
_, err = c.Sendf("%s", fn(msg))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ var gBeh = tg.NewGroupBehaviour().
|
||||||
c.Send("Hello, World!")
|
c.Send("Hello, World!")
|
||||||
}),
|
}),
|
||||||
tg.NewGroupCommand("mycounter").ActionFunc(func(c *tg.GC) {
|
tg.NewGroupCommand("mycounter").ActionFunc(func(c *tg.GC) {
|
||||||
d := c.SessionValue().(*UserData)
|
d := c.Session().Value.(*UserData)
|
||||||
c.Sendf("Your counter value is %d", d.Counter)
|
c.Sendf("Your counter value is %d", d.Counter)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
@ -200,10 +200,9 @@ func main() {
|
||||||
}
|
}
|
||||||
bot = bot.
|
bot = bot.
|
||||||
WithBehaviour(beh).
|
WithBehaviour(beh).
|
||||||
WithGroupBehaviour(gBeh)
|
WithGroupBehaviour(gBeh).
|
||||||
|
Debug(true)
|
||||||
|
|
||||||
bot.Debug = true
|
log.Printf("Authorized on account %s", bot.Api.Self.UserName)
|
||||||
|
|
||||||
log.Printf("Authorized on account %s", bot.Self.UserName)
|
|
||||||
bot.Run()
|
bot.Run()
|
||||||
}
|
}
|
||||||
|
|
70
tg/bot.go
70
tg/bot.go
|
@ -3,16 +3,18 @@ package tg
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
"fmt"
|
||||||
|
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Update = apix.Update
|
type Update = tgbotapi.Update
|
||||||
type Chat = apix.Chat
|
type Chat = tgbotapi.Chat
|
||||||
type User = apix.User
|
type User = tgbotapi.User
|
||||||
|
|
||||||
// The wrapper around Telegram API.
|
// The wrapper around Telegram API.
|
||||||
type Bot struct {
|
type Bot struct {
|
||||||
*apix.BotAPI
|
Api *tgbotapi.BotAPI
|
||||||
Me *User
|
Me *User
|
||||||
// Private bot behaviour.
|
// Private bot behaviour.
|
||||||
behaviour *Behaviour
|
behaviour *Behaviour
|
||||||
|
@ -26,28 +28,55 @@ type Bot struct {
|
||||||
|
|
||||||
// Return the new bot with empty sessions and behaviour.
|
// Return the new bot with empty sessions and behaviour.
|
||||||
func NewBot(token string) (*Bot, error) {
|
func NewBot(token string) (*Bot, error) {
|
||||||
bot, err := apix.NewBotAPI(token)
|
bot, err := tgbotapi.NewBotAPI(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Bot{
|
return &Bot{
|
||||||
BotAPI: bot,
|
Api: bot,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) SessionValueBySid(
|
func (bot *Bot) Debug(debug bool) *Bot {
|
||||||
sid SessionId,
|
bot.Api.Debug = debug
|
||||||
) (any, bool) {
|
return bot
|
||||||
v, ok := bot.sessions[sid]
|
|
||||||
return v.V, ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) GetGroupSessionValue(
|
func (bot *Bot) Send(
|
||||||
|
sid SessionId, v any,
|
||||||
|
) (*Message, error) {
|
||||||
|
sendable, ok := v.(Sendable)
|
||||||
|
if !ok {
|
||||||
|
cid := sid.ToApi()
|
||||||
|
str := tgbotapi.NewMessage(
|
||||||
|
cid, fmt.Sprint(v),
|
||||||
|
)
|
||||||
|
msg, err := bot.Api.Send(str)
|
||||||
|
return &msg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendable.Send(sid, bot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bot *Bot) Render(
|
||||||
|
sid SessionId, r Renderable,
|
||||||
|
) ([]*Message, error) {
|
||||||
|
return r.Render(sid, bot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bot *Bot) GetSession(
|
||||||
sid SessionId,
|
sid SessionId,
|
||||||
) (any, bool) {
|
) (*Session, bool) {
|
||||||
v, ok := bot.groupSessions[sid]
|
session, ok := bot.sessions[sid]
|
||||||
return v.V, 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 {
|
||||||
|
@ -78,10 +107,9 @@ func (bot *Bot) Run() error {
|
||||||
bot.groupBehaviour == nil {
|
bot.groupBehaviour == nil {
|
||||||
return errors.New("no behaviour defined")
|
return errors.New("no behaviour defined")
|
||||||
}
|
}
|
||||||
bot.Debug = true
|
uc := tgbotapi.NewUpdate(0)
|
||||||
uc := apix.NewUpdate(0)
|
|
||||||
uc.Timeout = 60
|
uc.Timeout = 60
|
||||||
updates := bot.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 {
|
||||||
|
@ -97,7 +125,7 @@ func (bot *Bot) Run() error {
|
||||||
go bot.handleGroup(chn)
|
go bot.handleGroup(chn)
|
||||||
}
|
}
|
||||||
|
|
||||||
me, _ := bot.GetMe()
|
me, _ := bot.Api.GetMe()
|
||||||
bot.Me = &me
|
bot.Me = &me
|
||||||
for u := range updates {
|
for u := range updates {
|
||||||
chn, ok := handles[u.FromChat().Type]
|
chn, ok := handles[u.FromChat().Type]
|
||||||
|
@ -167,7 +195,7 @@ func (bot *Bot) handleGroup(updates chan *Update) {
|
||||||
session := bot.groupSessions[sid]
|
session := bot.groupSessions[sid]
|
||||||
ctx := &groupContext{
|
ctx := &groupContext{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
GroupSession: session,
|
Session: session,
|
||||||
updates: make(chan *Update),
|
updates: make(chan *Update),
|
||||||
}
|
}
|
||||||
chn := make(chan *Update)
|
chn := make(chan *Update)
|
||||||
|
|
|
@ -1,60 +1 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context for interaction inside groups.
|
|
||||||
type groupContext struct {
|
|
||||||
*GroupSession
|
|
||||||
*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.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.
|
|
||||||
atName := msg.CommandWithAt()[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) error {
|
|
||||||
return c.Send(fmt.Sprintf(format, v...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends into the chat specified values converted to strings.
|
|
||||||
func (c *groupContext) Send(v ...any) error {
|
|
||||||
msg := apix.NewMessage(c.Id.ToTelegram(), fmt.Sprint(v...))
|
|
||||||
_, err := c.Bot.Send(msg)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
21
tg/file.go
21
tg/file.go
|
@ -6,6 +6,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileType int
|
type FileType int
|
||||||
|
@ -69,3 +71,22 @@ func (f *File) UploadData() (string, io.Reader, error) {
|
||||||
func (f *File) SendData() string {
|
func (f *File) SendData() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
func (f *File) Send(
|
||||||
|
sid SessionId, bot *Bot,
|
||||||
|
) (*Message, error) {
|
||||||
|
var chattable tgbotapi.Chattable
|
||||||
|
cid := sid.ToApi()
|
||||||
|
|
||||||
|
switch f.Type() {
|
||||||
|
case ImageFileType:
|
||||||
|
photo := tgbotapi.NewPhoto(cid, f)
|
||||||
|
photo.Caption = f.caption
|
||||||
|
chattable = photo
|
||||||
|
default:
|
||||||
|
return nil, UnknownFileTypeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := bot.Api.Send(chattable)
|
||||||
|
|
||||||
|
return &msg, err
|
||||||
|
}
|
||||||
|
|
74
tg/group.go
74
tg/group.go
|
@ -1,5 +1,11 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
|
)
|
||||||
|
|
||||||
// Customized actions for the group behaviour.
|
// Customized actions for the group behaviour.
|
||||||
type GroupAction interface {
|
type GroupAction interface {
|
||||||
Act(*GroupContext)
|
Act(*GroupContext)
|
||||||
|
@ -14,16 +20,70 @@ func (af GroupActionFunc) Act(a *GroupContext) {
|
||||||
|
|
||||||
type GC = GroupContext
|
type GC = GroupContext
|
||||||
|
|
||||||
func (c *GroupContext) SentFromSid() SessionId {
|
func (c *GroupContext) Session() *GroupSession {
|
||||||
return SessionId(c.SentFrom().ID)
|
session, _ := c.Bot.GetGroupSession(
|
||||||
}
|
SessionId(c.SentFrom().ID),
|
||||||
|
)
|
||||||
func (a *GroupContext) SessionValue() any {
|
return session
|
||||||
v, _ := a.Bot.SessionValueBySid(a.SentFromSid())
|
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupContext struct {
|
type GroupContext struct {
|
||||||
*groupContext
|
*groupContext
|
||||||
*Update
|
*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.
|
||||||
|
atName := msg.CommandWithAt()[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) error {
|
||||||
|
return c.Send(fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends into the chat specified values converted to strings.
|
||||||
|
func (c *groupContext) Send(v ...any) error {
|
||||||
|
msg := tgbotapi.NewMessage(
|
||||||
|
c.Session.Id.ToApi(),
|
||||||
|
fmt.Sprint(v...),
|
||||||
|
)
|
||||||
|
_, err := c.Bot.Api.Send(msg)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
*Session
|
Session *Session
|
||||||
*Bot
|
Bot *Bot
|
||||||
updates chan *Update
|
updates chan *Update
|
||||||
// Is true if currently reading the Update.
|
// Is true if currently reading the Update.
|
||||||
readingUpdate bool
|
readingUpdate bool
|
||||||
|
@ -21,7 +21,7 @@ type context struct {
|
||||||
|
|
||||||
// Goroutie function to handle each user.
|
// Goroutie function to handle each user.
|
||||||
func (c *context) handleUpdateChan(updates chan *Update) {
|
func (c *context) handleUpdateChan(updates chan *Update) {
|
||||||
beh := c.behaviour
|
beh := c.Bot.behaviour
|
||||||
|
|
||||||
if beh.Init != nil {
|
if beh.Init != nil {
|
||||||
c.run(beh.Init, nil)
|
c.run(beh.Init, nil)
|
||||||
|
@ -76,7 +76,7 @@ func (c *context) handleUpdateChan(updates chan *Update) {
|
||||||
)
|
)
|
||||||
data := u.CallbackQuery.Data
|
data := u.CallbackQuery.Data
|
||||||
|
|
||||||
_, err := c.Request(cb)
|
_, err := c.Bot.Api.Request(cb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -113,12 +113,6 @@ func (c *context) run(a Action, u *Update) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) SendFile(f *File) error {
|
|
||||||
switch f.typ {
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the next update ignoring current screen.
|
// Returns the next update ignoring current screen.
|
||||||
func (c *context) ReadUpdate() (*Update, error) {
|
func (c *context) ReadUpdate() (*Update, error) {
|
||||||
c.readingUpdate = true
|
c.readingUpdate = true
|
||||||
|
@ -145,36 +139,17 @@ func (c *context) ReadTextMessage() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends to the user specified text.
|
// Sends to the user specified text.
|
||||||
func (c *context) Send(values ...any) error {
|
func (c *context) Send(v any) (*Message, error) {
|
||||||
cid := c.Id.ToTelegram()
|
return c.Bot.Send(c.Session.Id, v)
|
||||||
for _, v := range values {
|
|
||||||
var msg tgbotapi.Chattable
|
|
||||||
|
|
||||||
switch rv := v.(type) {
|
|
||||||
case *File:
|
|
||||||
switch rv.Type() {
|
|
||||||
case ImageFileType:
|
|
||||||
msg = tgbotapi.NewPhoto(cid, rv)
|
|
||||||
default:
|
|
||||||
return UnknownFileTypeErr
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
msg = tgbotapi.NewMessage(
|
|
||||||
cid, fmt.Sprint(v),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := c.Bot.Send(msg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the formatted with fmt.Sprintf message to the user.
|
// Sends the formatted with fmt.Sprintf message to the user.
|
||||||
func (c *context) Sendf(format string, v ...any) error {
|
func (c *context) Sendf(format string, v ...any) (*Message, error) {
|
||||||
return c.Send(fmt.Sprintf(format, v...))
|
msg, err := c.Send(fmt.Sprintf(format, v...))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return msg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface to interact with the user.
|
// Interface to interact with the user.
|
||||||
|
@ -198,7 +173,7 @@ func (af ActionFunc) Act(c *Context) {
|
||||||
type ScreenChange ScreenId
|
type ScreenChange ScreenId
|
||||||
|
|
||||||
func (sc ScreenChange) Act(c *Context) {
|
func (sc ScreenChange) Act(c *Context) {
|
||||||
if !c.behaviour.ScreenExist(ScreenId(sc)) {
|
if !c.Bot.behaviour.ScreenExist(ScreenId(sc)) {
|
||||||
panic(ScreenNotExistErr)
|
panic(ScreenNotExistErr)
|
||||||
}
|
}
|
||||||
err := c.ChangeScreen(ScreenId(sc))
|
err := c.ChangeScreen(ScreenId(sc))
|
||||||
|
@ -211,7 +186,7 @@ type C = Context
|
||||||
|
|
||||||
// Changes screen of user to the Id one.
|
// Changes screen of user to the Id one.
|
||||||
func (c *Context) ChangeScreen(screenId ScreenId) error {
|
func (c *Context) ChangeScreen(screenId ScreenId) error {
|
||||||
if !c.behaviour.ScreenExist(screenId) {
|
if !c.Bot.behaviour.ScreenExist(screenId) {
|
||||||
return ScreenNotExistErr
|
return ScreenNotExistErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,18 +199,13 @@ func (c *Context) ChangeScreen(screenId ScreenId) error {
|
||||||
|
|
||||||
// Getting the screen and changing to
|
// Getting the screen and changing to
|
||||||
// then executing its action.
|
// then executing its action.
|
||||||
screen := c.behaviour.Screens[screenId]
|
screen := c.Bot.behaviour.Screens[screenId]
|
||||||
c.prevScreen = c.curScreen
|
c.prevScreen = c.curScreen
|
||||||
c.curScreen = screen
|
c.curScreen = screen
|
||||||
screen.Render(c.context)
|
screen.Render(c.Session.Id, c.Bot)
|
||||||
if screen.Action != nil {
|
if screen.Action != nil {
|
||||||
c.run(screen.Action, c.Update)
|
c.run(screen.Action, c.Update)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) SessionValue() any {
|
|
||||||
v, _ := c.SessionValueBySid(c.Id)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
58
tg/screen.go
58
tg/screen.go
|
@ -1,7 +1,7 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Unique identifier for the screen.
|
// Unique identifier for the screen.
|
||||||
|
@ -62,14 +62,18 @@ func (s *Screen) ActionFunc(a ActionFunc) *Screen {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renders output of the screen only to the side of the user.
|
// Renders output of the screen only to the side of the user.
|
||||||
func (s *Screen) Render(c *context) error {
|
func (s *Screen) Render(
|
||||||
id := c.Id.ToTelegram()
|
sid SessionId, bot *Bot,
|
||||||
|
) ([]*Message, error) {
|
||||||
|
cid := sid.ToApi()
|
||||||
kbd := s.Keyboard
|
kbd := s.Keyboard
|
||||||
iKbd := s.InlineKeyboard
|
iKbd := s.InlineKeyboard
|
||||||
|
|
||||||
var ch [2]apix.Chattable
|
var ch [2]tgbotapi.Chattable
|
||||||
var txt string
|
var txt string
|
||||||
|
|
||||||
|
msgs := []*Message{}
|
||||||
|
|
||||||
// Screen text and inline keyboard.
|
// Screen text and inline keyboard.
|
||||||
if s.Text != "" {
|
if s.Text != "" {
|
||||||
txt = s.Text
|
txt = s.Text
|
||||||
|
@ -82,23 +86,27 @@ func (s *Screen) Render(c *context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if txt != "" {
|
if txt != "" {
|
||||||
msg := apix.NewMessage(id, txt)
|
msgConfig := tgbotapi.NewMessage(cid, txt)
|
||||||
if iKbd != nil {
|
if iKbd != nil {
|
||||||
msg.ReplyMarkup = iKbd.toTelegramInline()
|
msgConfig.ReplyMarkup = iKbd.toTelegramInline()
|
||||||
} else if kbd != nil {
|
} else if kbd != nil {
|
||||||
msg.ReplyMarkup = kbd.toTelegramReply()
|
msgConfig.ReplyMarkup = kbd.toTelegramReply()
|
||||||
if _, err := c.Bot.Send(msg); err != nil {
|
msg, err := bot.Api.Send(msgConfig)
|
||||||
return err
|
if err != nil {
|
||||||
|
return msgs, err
|
||||||
}
|
}
|
||||||
return nil
|
msgs = append(msgs, &msg)
|
||||||
|
return msgs, nil
|
||||||
} else {
|
} else {
|
||||||
msg.ReplyMarkup = apix.NewRemoveKeyboard(true)
|
msgConfig.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
||||||
if _, err := c.Bot.Send(msg); err != nil {
|
msg, err := bot.Api.Send(msgConfig)
|
||||||
return err
|
if err != nil {
|
||||||
|
return msgs, err
|
||||||
}
|
}
|
||||||
return nil
|
msgs = append(msgs, &msg)
|
||||||
|
return msgs, nil
|
||||||
}
|
}
|
||||||
ch[0] = msg
|
ch[0] = msgConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen text and reply keyboard.
|
// Screen text and reply keyboard.
|
||||||
|
@ -109,23 +117,25 @@ func (s *Screen) Render(c *context) error {
|
||||||
} else {
|
} else {
|
||||||
txt = ">"
|
txt = ">"
|
||||||
}
|
}
|
||||||
msg := apix.NewMessage(id, txt)
|
msgConfig := tgbotapi.NewMessage(cid, txt)
|
||||||
msg.ReplyMarkup = kbd.toTelegramReply()
|
msgConfig.ReplyMarkup = kbd.toTelegramReply()
|
||||||
ch[1] = msg
|
ch[1] = msgConfig
|
||||||
} else {
|
} else {
|
||||||
// Removing keyboard if there is none.
|
// Removing keyboard if there is none.
|
||||||
msg := apix.NewMessage(id, ">")
|
msgConfig := tgbotapi.NewMessage(cid, ">")
|
||||||
msg.ReplyMarkup = apix.NewRemoveKeyboard(true)
|
msgConfig.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
||||||
ch[1] = msg
|
ch[1] = msgConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range ch {
|
for _, m := range ch {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
if _, err := c.Bot.Send(m); err != nil {
|
msg, err := bot.Api.Send(m)
|
||||||
return err
|
if err != nil {
|
||||||
|
return msgs, err
|
||||||
}
|
}
|
||||||
|
msgs = append(msgs, &msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return msgs, nil
|
||||||
}
|
}
|
||||||
|
|
11
tg/send.go
Normal file
11
tg/send.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package tg
|
||||||
|
|
||||||
|
// Implementing the interface lets the
|
||||||
|
// value to be sent.
|
||||||
|
type Sendable interface {
|
||||||
|
Send(SessionId, *Bot) (*Message, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Renderable interface {
|
||||||
|
Render(SessionId, *Bot) ([]*Message, error)
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ package tg
|
||||||
type SessionId int64
|
type SessionId int64
|
||||||
|
|
||||||
// Convert the SessionId to Telegram API's type.
|
// Convert the SessionId to Telegram API's type.
|
||||||
func (si SessionId) ToTelegram() int64 {
|
func (si SessionId) ToApi() int64 {
|
||||||
return int64(si)
|
return int64(si)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,14 +15,13 @@ type Session struct {
|
||||||
// Id of the chat of the user.
|
// Id of the chat of the user.
|
||||||
Id SessionId
|
Id SessionId
|
||||||
// Custom value for each user.
|
// Custom value for each user.
|
||||||
V any
|
Value any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return new empty session with specified user ID.
|
// Return new empty session with specified user ID.
|
||||||
func NewSession(id SessionId) *Session {
|
func NewSession(id SessionId) *Session {
|
||||||
return &Session{
|
return &Session{
|
||||||
Id: id,
|
Id: id,
|
||||||
V: make(map[string]any),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,14 +38,13 @@ func (sm SessionMap) Add(sid SessionId) {
|
||||||
type GroupSession struct {
|
type GroupSession struct {
|
||||||
Id SessionId
|
Id SessionId
|
||||||
// Information for each user in the group.
|
// Information for each user in the group.
|
||||||
V map[SessionId]any
|
Value any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns new empty group session with specified group and user IDs.
|
// Returns new empty group session with specified group and user IDs.
|
||||||
func NewGroupSession(id SessionId) *GroupSession {
|
func NewGroupSession(id SessionId) *GroupSession {
|
||||||
return &GroupSession{
|
return &GroupSession{
|
||||||
Id: id,
|
Id: id,
|
||||||
V: make(map[SessionId]any),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue