Great refactoring. Should put more of the handling into the Actions.
This commit is contained in:
parent
b2748a8cee
commit
5b00189ea2
9 changed files with 227 additions and 166 deletions
|
@ -20,7 +20,7 @@ var (
|
||||||
startScreenButton = tg.NewButton("🏠 To the start screen").
|
startScreenButton = tg.NewButton("🏠 To the start screen").
|
||||||
ScreenChange("start")
|
ScreenChange("start")
|
||||||
|
|
||||||
incDecKeyboard = tg.NewKeyboard("").Row(
|
incDecKeyboard = tg.NewInline().Row(
|
||||||
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
||||||
d := c.Session.Value.(*UserData)
|
d := c.Session.Value.(*UserData)
|
||||||
d.Counter++
|
d.Counter++
|
||||||
|
@ -35,7 +35,7 @@ var (
|
||||||
startScreenButton,
|
startScreenButton,
|
||||||
)
|
)
|
||||||
|
|
||||||
navKeyboard = tg.NewKeyboard("Choose your interest").
|
navKeyboard = tg.NewReply().
|
||||||
WithOneTime(true).
|
WithOneTime(true).
|
||||||
Row(
|
Row(
|
||||||
tg.NewButton("Inc/Dec").ScreenChange("inc/dec"),
|
tg.NewButton("Inc/Dec").ScreenChange("inc/dec"),
|
||||||
|
@ -46,7 +46,7 @@ var (
|
||||||
tg.NewButton("Send location").ScreenChange("send-location"),
|
tg.NewButton("Send location").ScreenChange("send-location"),
|
||||||
)
|
)
|
||||||
|
|
||||||
sendLocationKeyboard = tg.NewKeyboard("Press the button to send your location").
|
sendLocationKeyboard = tg.NewReply().
|
||||||
Row(
|
Row(
|
||||||
tg.NewButton("Send location").
|
tg.NewButton("Send location").
|
||||||
WithSendLocation(true).
|
WithSendLocation(true).
|
||||||
|
@ -64,10 +64,10 @@ var (
|
||||||
l.Heading,
|
l.Heading,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
_, err = c.Send("Somehow wrong location was sent")
|
_, err = c.Sendf("Somehow wrong location was sent")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Send(err)
|
c.Sendf("%q", err)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
).Row(
|
).Row(
|
||||||
|
@ -75,7 +75,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// The keyboard to return to the start screen.
|
// The keyboard to return to the start screen.
|
||||||
navToStartKeyboard = tg.NewKeyboard("").Row(
|
navToStartKeyboard = tg.NewReply().Row(
|
||||||
startScreenButton,
|
startScreenButton,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -87,7 +87,7 @@ var beh = tg.NewBehaviour().
|
||||||
|
|
||||||
}). // On any message update before the bot created session.
|
}). // On any message update before the bot created session.
|
||||||
WithPreStartFunc(func(c *tg.Context){
|
WithPreStartFunc(func(c *tg.Context){
|
||||||
c.Send("Please, use the /start command to start the bot")
|
c.Sendf("Please, use the /start command to start the bot")
|
||||||
}).WithScreens(
|
}).WithScreens(
|
||||||
tg.NewScreen("start").
|
tg.NewScreen("start").
|
||||||
WithText(
|
WithText(
|
||||||
|
@ -96,10 +96,10 @@ var beh = tg.NewBehaviour().
|
||||||
" understand of how the API works, so just"+
|
" understand of how the API works, so just"+
|
||||||
" horse around a bit to guess everything out"+
|
" horse around a bit to guess everything out"+
|
||||||
" by yourself!",
|
" by yourself!",
|
||||||
).WithKeyboard(navKeyboard).
|
).WithReply(navKeyboard).
|
||||||
// The inline keyboard with link to GitHub page.
|
// The inline keyboard with link to GitHub page.
|
||||||
WithIKeyboard(
|
WithInline(
|
||||||
tg.NewKeyboard("istart").Row(
|
tg.NewInline().Row(
|
||||||
tg.NewButton("GoT Github page").
|
tg.NewButton("GoT Github page").
|
||||||
WithUrl("https://github.com/mojosa-software/got"),
|
WithUrl("https://github.com/mojosa-software/got"),
|
||||||
),
|
),
|
||||||
|
@ -112,7 +112,7 @@ var beh = tg.NewBehaviour().
|
||||||
"by saving the counter for each of users "+
|
"by saving the counter for each of users "+
|
||||||
"separately. ",
|
"separately. ",
|
||||||
).
|
).
|
||||||
WithKeyboard(incDecKeyboard).
|
WithReply(&tg.ReplyKeyboard{Keyboard: incDecKeyboard.Keyboard}).
|
||||||
// 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.Session.Value.(*UserData)
|
d := c.Session.Value.(*UserData)
|
||||||
|
@ -121,19 +121,19 @@ var beh = tg.NewBehaviour().
|
||||||
|
|
||||||
tg.NewScreen("upper-case").
|
tg.NewScreen("upper-case").
|
||||||
WithText("Type text and the bot will send you the upper case version to you").
|
WithText("Type text and the bot will send you the upper case version to you").
|
||||||
WithKeyboard(navToStartKeyboard).
|
WithReply(navToStartKeyboard).
|
||||||
ActionFunc(mutateMessage(strings.ToUpper)),
|
ActionFunc(mutateMessage(strings.ToUpper)),
|
||||||
|
|
||||||
tg.NewScreen("lower-case").
|
tg.NewScreen("lower-case").
|
||||||
WithText("Type text and the bot will send you the lower case version").
|
WithText("Type text and the bot will send you the lower case version").
|
||||||
WithKeyboard(navToStartKeyboard).
|
WithReply(navToStartKeyboard).
|
||||||
ActionFunc(mutateMessage(strings.ToLower)),
|
ActionFunc(mutateMessage(strings.ToLower)),
|
||||||
|
|
||||||
tg.NewScreen("send-location").
|
tg.NewScreen("send-location").
|
||||||
WithText("Send your location and I will tell where you are!").
|
WithText("Send your location and I will tell where you are!").
|
||||||
WithKeyboard(sendLocationKeyboard).
|
WithReply(sendLocationKeyboard).
|
||||||
WithIKeyboard(
|
WithInline(
|
||||||
tg.NewKeyboard("").Row(
|
tg.NewInline().Row(
|
||||||
tg.NewButton("Check").
|
tg.NewButton("Check").
|
||||||
WithData("check").
|
WithData("check").
|
||||||
ActionFunc(func(a *tg.Context) {
|
ActionFunc(func(a *tg.Context) {
|
||||||
|
@ -151,12 +151,12 @@ var beh = tg.NewBehaviour().
|
||||||
tg.NewCommand("hello").
|
tg.NewCommand("hello").
|
||||||
Desc("sends the 'Hello, World!' message back").
|
Desc("sends the 'Hello, World!' message back").
|
||||||
ActionFunc(func(c *tg.Context) {
|
ActionFunc(func(c *tg.Context) {
|
||||||
c.Send("Hello, World!")
|
c.Sendf("Hello, World!")
|
||||||
}),
|
}),
|
||||||
tg.NewCommand("read").
|
tg.NewCommand("read").
|
||||||
Desc("reads a string and sends it back").
|
Desc("reads a string and sends it back").
|
||||||
ActionFunc(func(c *tg.Context) {
|
ActionFunc(func(c *tg.Context) {
|
||||||
c.Send("Type some text:")
|
c.Sendf("Type some text:")
|
||||||
msg, err := c.ReadTextMessage()
|
msg, err := c.ReadTextMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,7 +8,6 @@ type Behaviour struct {
|
||||||
PreStart *action
|
PreStart *action
|
||||||
Init *action
|
Init *action
|
||||||
Screens ScreenMap
|
Screens ScreenMap
|
||||||
Keyboards KeyboardMap
|
|
||||||
Commands CommandMap
|
Commands CommandMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ type Behaviour struct {
|
||||||
func NewBehaviour() *Behaviour {
|
func NewBehaviour() *Behaviour {
|
||||||
return &Behaviour{
|
return &Behaviour{
|
||||||
Screens: make(ScreenMap),
|
Screens: make(ScreenMap),
|
||||||
Keyboards: make(KeyboardMap),
|
|
||||||
Commands: make(CommandMap),
|
Commands: make(CommandMap),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
tg/bot.go
36
tg/bot.go
|
@ -3,7 +3,7 @@ package tg
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"fmt"
|
//"fmt"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
@ -25,6 +25,7 @@ type Bot struct {
|
||||||
sessions SessionMap
|
sessions SessionMap
|
||||||
groupSessions GroupSessionMap
|
groupSessions GroupSessionMap
|
||||||
value any
|
value any
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the new bot with empty sessions and behaviour.
|
// Return the new bot with empty sessions and behaviour.
|
||||||
|
@ -58,25 +59,36 @@ func (bot *Bot) Debug(debug bool) *Bot {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) Send(
|
func (bot *Bot) Send(
|
||||||
sid SessionId, v any,
|
sid SessionId, v Sendable,
|
||||||
) (*Message, error) {
|
) (*Message, error) {
|
||||||
sendable, ok := v.(Sendable)
|
config, err := v.SendConfig(sid, bot)
|
||||||
if !ok {
|
if err != nil {
|
||||||
cid := sid.ToApi()
|
return nil, err
|
||||||
str := tgbotapi.NewMessage(
|
|
||||||
cid, fmt.Sprint(v),
|
|
||||||
)
|
|
||||||
msg, err := bot.Api.Send(str)
|
|
||||||
return &msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendable.Send(sid, bot)
|
msg, err := bot.Api.Send(config.ToApi())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) Render(
|
func (bot *Bot) Render(
|
||||||
sid SessionId, r Renderable,
|
sid SessionId, r Renderable,
|
||||||
) ([]*Message, error) {
|
) ([]*Message, error) {
|
||||||
return r.Render(sid, bot)
|
configs, err := r.Render(sid, bot)
|
||||||
|
if err != nil {
|
||||||
|
return []*Message{}, err
|
||||||
|
}
|
||||||
|
messages := []*Message{}
|
||||||
|
for _, config := range configs {
|
||||||
|
msg, err := bot.Api.Send(config.ToApi())
|
||||||
|
if err != nil {
|
||||||
|
return messages, err
|
||||||
|
}
|
||||||
|
messages = append(messages, &msg)
|
||||||
|
}
|
||||||
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) GetSession(
|
func (bot *Bot) GetSession(
|
||||||
|
|
13
tg/file.go
13
tg/file.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PhotoConfig = tgbotapi.PhotoConfig
|
||||||
type FileType int
|
type FileType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -71,22 +72,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(
|
func (f *File) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionId, bot *Bot,
|
||||||
) (*Message, error) {
|
) (*SendConfig, error) {
|
||||||
var chattable tgbotapi.Chattable
|
var config SendConfig
|
||||||
cid := sid.ToApi()
|
cid := sid.ToApi()
|
||||||
|
|
||||||
switch f.Type() {
|
switch f.Type() {
|
||||||
case ImageFileType:
|
case ImageFileType:
|
||||||
photo := tgbotapi.NewPhoto(cid, f)
|
photo := tgbotapi.NewPhoto(cid, f)
|
||||||
photo.Caption = f.caption
|
photo.Caption = f.caption
|
||||||
chattable = photo
|
|
||||||
|
config.Image = &photo
|
||||||
default:
|
default:
|
||||||
return nil, UnknownFileTypeErr
|
return nil, UnknownFileTypeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := bot.Api.Send(chattable)
|
|
||||||
|
|
||||||
return &msg, err
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
102
tg/keyboard.go
102
tg/keyboard.go
|
@ -1,57 +1,48 @@
|
||||||
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// The general keyboard type used both in Reply and Inline.
|
||||||
var otherKeyboard = tgbotapi.NewReplyKeyboard(
|
|
||||||
tgbotapi.NewKeyboardButtonRow(
|
|
||||||
tgbotapi.NewKeyboardButton("a"),
|
|
||||||
tgbotapi.NewKeyboardButton("b"),
|
|
||||||
tgbotapi.NewKeyboardButton("c"),
|
|
||||||
),
|
|
||||||
tgbotapi.NewKeyboardButtonRow(
|
|
||||||
tgbotapi.NewKeyboardButton("d"),
|
|
||||||
tgbotapi.NewKeyboardButton("e"),
|
|
||||||
tgbotapi.NewKeyboardButton("f"),
|
|
||||||
),
|
|
||||||
)*/
|
|
||||||
|
|
||||||
type KeyboardId string
|
|
||||||
|
|
||||||
// The type represents reply keyboard which
|
|
||||||
// is supposed to be showed on a Screen.
|
|
||||||
type Keyboard struct {
|
type Keyboard struct {
|
||||||
// Text to be displayed with the keyboard.
|
|
||||||
Text string
|
|
||||||
// Rows to be displayed once the
|
|
||||||
// keyboard is sent.
|
|
||||||
Rows []ButtonRow
|
Rows []ButtonRow
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplyKeyboard struct {
|
||||||
|
Keyboard
|
||||||
|
// If true will be removed after one press.
|
||||||
OneTime bool
|
OneTime bool
|
||||||
Inline bool
|
// If true will remove the keyboard on send.
|
||||||
|
Remove bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyboardMap map[KeyboardId]*Keyboard
|
// The keyboard to be emdedded into the messages.
|
||||||
|
type InlineKeyboard struct {
|
||||||
// Return the new reply keyboard with rows as specified.
|
Keyboard
|
||||||
func NewKeyboard(text string) *Keyboard {
|
|
||||||
return &Keyboard{
|
|
||||||
Text: text,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kbd *Keyboard) TelegramMarkup() any {
|
func NewInline() *InlineKeyboard {
|
||||||
if kbd.Inline {
|
ret := &InlineKeyboard{}
|
||||||
return kbd.toTelegramInline()
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
return kbd.toTelegramReply()
|
func NewReply() *ReplyKeyboard {
|
||||||
|
ret := &ReplyKeyboard {}
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a new button row to the current keyboard.
|
// Adds a new button row to the current keyboard.
|
||||||
func (kbd *Keyboard) Row(btns ...*Button) *Keyboard {
|
func (kbd *InlineKeyboard) Row(btns ...*Button) *InlineKeyboard {
|
||||||
|
// For empty row. We do not need that.
|
||||||
|
if len(btns) < 1 {
|
||||||
|
return kbd
|
||||||
|
}
|
||||||
|
kbd.Rows = append(kbd.Rows, btns)
|
||||||
|
return kbd
|
||||||
|
}
|
||||||
|
// Adds a new button row to the current keyboard.
|
||||||
|
func (kbd *ReplyKeyboard) Row(btns ...*Button) *ReplyKeyboard {
|
||||||
// For empty row. We do not need that.
|
// For empty row. We do not need that.
|
||||||
if len(btns) < 1 {
|
if len(btns) < 1 {
|
||||||
return kbd
|
return kbd
|
||||||
|
@ -61,10 +52,15 @@ func (kbd *Keyboard) Row(btns ...*Button) *Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the Keyboard to the Telegram API type of reply keyboard.
|
// Convert the Keyboard to the Telegram API type of reply keyboard.
|
||||||
func (kbd *Keyboard) toTelegramReply() apix.ReplyKeyboardMarkup {
|
func (kbd *ReplyKeyboard) ToApi() any {
|
||||||
rows := [][]apix.KeyboardButton{}
|
// Shades everything.
|
||||||
|
if kbd.Remove {
|
||||||
|
return tgbotapi.NewRemoveKeyboard(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := [][]tgbotapi.KeyboardButton{}
|
||||||
for _, row := range kbd.Rows {
|
for _, row := range kbd.Rows {
|
||||||
buttons := []apix.KeyboardButton{}
|
buttons := []tgbotapi.KeyboardButton{}
|
||||||
for _, button := range row {
|
for _, button := range row {
|
||||||
buttons = append(buttons, button.ToTelegram())
|
buttons = append(buttons, button.ToTelegram())
|
||||||
}
|
}
|
||||||
|
@ -72,37 +68,37 @@ func (kbd *Keyboard) toTelegramReply() apix.ReplyKeyboardMarkup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if kbd.OneTime {
|
if kbd.OneTime {
|
||||||
return apix.NewOneTimeReplyKeyboard(rows...)
|
return tgbotapi.NewOneTimeReplyKeyboard(rows...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return apix.NewReplyKeyboard(rows...)
|
return tgbotapi.NewReplyKeyboard(rows...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kbd *Keyboard) toTelegramInline() apix.InlineKeyboardMarkup {
|
func (kbd *InlineKeyboard) ToApi() tgbotapi.InlineKeyboardMarkup {
|
||||||
rows := [][]apix.InlineKeyboardButton{}
|
rows := [][]tgbotapi.InlineKeyboardButton{}
|
||||||
for _, row := range kbd.Rows {
|
for _, row := range kbd.Rows {
|
||||||
buttons := []apix.InlineKeyboardButton{}
|
buttons := []tgbotapi.InlineKeyboardButton{}
|
||||||
for _, button := range row {
|
for _, button := range row {
|
||||||
buttons = append(buttons, button.ToTelegramInline())
|
buttons = append(buttons, button.ToTelegramInline())
|
||||||
}
|
}
|
||||||
rows = append(rows, buttons)
|
rows = append(rows, buttons)
|
||||||
}
|
}
|
||||||
|
|
||||||
return apix.NewInlineKeyboardMarkup(rows...)
|
return tgbotapi.NewInlineKeyboardMarkup(rows...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kbd *Keyboard) WithOneTime(oneTime bool) *Keyboard {
|
func (kbd *ReplyKeyboard) WithRemove(remove bool) *ReplyKeyboard {
|
||||||
|
kbd.Remove = remove
|
||||||
|
return kbd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kbd *ReplyKeyboard) WithOneTime(oneTime bool) *ReplyKeyboard {
|
||||||
kbd.OneTime = oneTime
|
kbd.OneTime = oneTime
|
||||||
return kbd
|
return kbd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kbd *Keyboard) WithInline(inline bool) *Keyboard {
|
|
||||||
kbd.Inline = inline
|
|
||||||
return kbd
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the map of buttons. Used to define the Action.
|
// Returns the map of buttons. Used to define the Action.
|
||||||
func (kbd *Keyboard) buttonMap() ButtonMap {
|
func (kbd Keyboard) buttonMap() ButtonMap {
|
||||||
ret := make(ButtonMap)
|
ret := make(ButtonMap)
|
||||||
for _, vi := range kbd.Rows {
|
for _, vi := range kbd.Rows {
|
||||||
for _, vj := range vi {
|
for _, vj := range vi {
|
||||||
|
|
51
tg/message.go
Normal file
51
tg/message.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package tg
|
||||||
|
|
||||||
|
import (
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageConfig struct {
|
||||||
|
To SessionId
|
||||||
|
ReplyTo MessageId
|
||||||
|
Text string
|
||||||
|
Inline *InlineKeyboard
|
||||||
|
Reply *ReplyKeyboard
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMessage(to SessionId, text string) *MessageConfig {
|
||||||
|
ret := &MessageConfig{}
|
||||||
|
ret.To = to
|
||||||
|
ret.Text = text
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *MessageConfig) WithInline(
|
||||||
|
inline *InlineKeyboard,
|
||||||
|
) *MessageConfig {
|
||||||
|
config.Inline = inline
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *MessageConfig) WithReply(
|
||||||
|
reply *ReplyKeyboard,
|
||||||
|
) *MessageConfig {
|
||||||
|
config.Reply = reply
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *MessageConfig) SendConfig(
|
||||||
|
sid SessionId, bot *Bot,
|
||||||
|
) (*SendConfig, error) {
|
||||||
|
var ret SendConfig
|
||||||
|
msg := tgbotapi.NewMessage(config.To.ToApi(), config.Text)
|
||||||
|
if config.Inline != nil {
|
||||||
|
msg.ReplyMarkup = config.Inline.ToApi()
|
||||||
|
}
|
||||||
|
// Reply shades the inline.
|
||||||
|
if config.Reply != nil {
|
||||||
|
msg.ReplyMarkup = config.Reply.ToApi()
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Message = &msg
|
||||||
|
return &ret, nil
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ func (c *context) handleUpdateChan(updates chan *Update) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Simple messages handling.
|
// Simple messages handling.
|
||||||
kbd := screen.Keyboard
|
kbd := screen.Reply
|
||||||
if kbd == nil {
|
if kbd == nil {
|
||||||
if c.readingUpdate {
|
if c.readingUpdate {
|
||||||
c.updates <- u
|
c.updates <- u
|
||||||
|
@ -102,7 +102,7 @@ func (c *context) handleUpdateChan(updates chan *Update) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
kbd := screen.InlineKeyboard
|
kbd := screen.Inline
|
||||||
if kbd == nil {
|
if kbd == nil {
|
||||||
if c.readingUpdate {
|
if c.readingUpdate {
|
||||||
c.updates <- u
|
c.updates <- u
|
||||||
|
@ -160,14 +160,16 @@ func (c *context) ReadTextMessage() (string, error) {
|
||||||
return u.Message.Text, nil
|
return u.Message.Text, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends to the user specified text.
|
// Sends to the Sendable object.
|
||||||
func (c *context) Send(v any) (*Message, error) {
|
func (c *context) Send(v Sendable) (*Message, error) {
|
||||||
return c.Bot.Send(c.Session.Id, v)
|
return c.Bot.Send(c.Session.Id, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) (*Message, error) {
|
func (c *context) Sendf(format string, v ...any) (*Message, error) {
|
||||||
msg, err := c.Send(fmt.Sprintf(format, v...))
|
msg, err := c.Send(NewMessage(
|
||||||
|
c.Session.Id, fmt.Sprintf(format, v...),
|
||||||
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -224,7 +226,7 @@ func (c *Context) ChangeScreen(screenId ScreenId) error {
|
||||||
screen := c.Bot.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.Session.Id, c.Bot)
|
c.Bot.Render(c.Session.Id, screen)
|
||||||
if screen.Action != nil {
|
if screen.Action != nil {
|
||||||
c.run(screen.Action, c.Update)
|
c.run(screen.Action, c.Update)
|
||||||
}
|
}
|
||||||
|
|
103
tg/screen.go
103
tg/screen.go
|
@ -15,9 +15,9 @@ type Screen struct {
|
||||||
// reached.
|
// reached.
|
||||||
Text string
|
Text string
|
||||||
// The keyboard to be sent in the message part.
|
// The keyboard to be sent in the message part.
|
||||||
InlineKeyboard *Keyboard
|
Inline *InlineKeyboard
|
||||||
// Keyboard to be displayed on the screen.
|
// Keyboard to be displayed on the screen.
|
||||||
Keyboard *Keyboard
|
Reply *ReplyKeyboard
|
||||||
// Action called on the reaching the screen.
|
// Action called on the reaching the screen.
|
||||||
Action *action
|
Action *action
|
||||||
}
|
}
|
||||||
|
@ -38,17 +38,13 @@ func (s *Screen) WithText(text string) *Screen {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screen) WithInlineKeyboard(ikbd *Keyboard) *Screen {
|
func (s *Screen) WithInline(ikbd *InlineKeyboard) *Screen {
|
||||||
s.InlineKeyboard = ikbd
|
s.Inline= ikbd
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screen) WithIKeyboard(ikbd *Keyboard) *Screen {
|
func (s *Screen) WithReply(kbd *ReplyKeyboard) *Screen {
|
||||||
return s.WithInlineKeyboard(ikbd)
|
s.Reply = kbd
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Screen) WithKeyboard(kbd *Keyboard) *Screen {
|
|
||||||
s.Keyboard = kbd
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,81 +57,54 @@ func (s *Screen) ActionFunc(a ActionFunc) *Screen {
|
||||||
return s.WithAction(a)
|
return s.WithAction(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renders output of the screen only to the side of the user.
|
|
||||||
func (s *Screen) Render(
|
func (s *Screen) Render(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionId, bot *Bot,
|
||||||
) ([]*Message, error) {
|
) ([]*SendConfig, error) {
|
||||||
cid := sid.ToApi()
|
cid := sid.ToApi()
|
||||||
kbd := s.Keyboard
|
reply := s.Reply
|
||||||
iKbd := s.InlineKeyboard
|
inline := s.Inline
|
||||||
|
ret := []*SendConfig{}
|
||||||
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
|
||||||
} else if iKbd != nil {
|
} else if inline != nil {
|
||||||
if iKbd.Text != "" {
|
// Default to send the keyboard.
|
||||||
txt = iKbd.Text
|
txt = ">"
|
||||||
} else {
|
|
||||||
// Default to send the keyboard.
|
|
||||||
txt = ">"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if txt != "" {
|
if txt != "" {
|
||||||
msgConfig := tgbotapi.NewMessage(cid, txt)
|
msgConfig := tgbotapi.NewMessage(cid, txt)
|
||||||
if iKbd != nil {
|
if inline != nil {
|
||||||
msgConfig.ReplyMarkup = iKbd.toTelegramInline()
|
msgConfig.ReplyMarkup = inline.ToApi()
|
||||||
} else if kbd != nil {
|
} else if reply != nil {
|
||||||
msgConfig.ReplyMarkup = kbd.toTelegramReply()
|
msgConfig.ReplyMarkup = reply.ToApi()
|
||||||
msg, err := bot.Api.Send(msgConfig)
|
ret = append(ret, &SendConfig{Message: &msgConfig})
|
||||||
if err != nil {
|
return ret, nil
|
||||||
return msgs, err
|
|
||||||
}
|
|
||||||
msgs = append(msgs, &msg)
|
|
||||||
return msgs, nil
|
|
||||||
} else {
|
} else {
|
||||||
msgConfig.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
msgConfig.ReplyMarkup = NewReply().
|
||||||
msg, err := bot.Api.Send(msgConfig)
|
WithRemove(true).
|
||||||
if err != nil {
|
ToApi()
|
||||||
return msgs, err
|
ret = append(ret, &SendConfig{Message: &msgConfig})
|
||||||
}
|
return ret, nil
|
||||||
msgs = append(msgs, &msg)
|
|
||||||
return msgs, nil
|
|
||||||
}
|
}
|
||||||
ch[0] = msgConfig
|
ret = append(ret, &SendConfig{Message: &msgConfig})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen text and reply keyboard.
|
// Screen text and reply keyboard.
|
||||||
txt = ""
|
if reply != nil {
|
||||||
if kbd != nil {
|
msgConfig := tgbotapi.NewMessage(cid, ">")
|
||||||
if kbd.Text != "" {
|
msgConfig.ReplyMarkup = reply.ToApi()
|
||||||
txt = kbd.Text
|
ret = append(ret, &SendConfig{
|
||||||
} else {
|
Message: &msgConfig,
|
||||||
txt = ">"
|
})
|
||||||
}
|
|
||||||
msgConfig := tgbotapi.NewMessage(cid, txt)
|
|
||||||
msgConfig.ReplyMarkup = kbd.toTelegramReply()
|
|
||||||
ch[1] = msgConfig
|
|
||||||
} else {
|
} else {
|
||||||
// Removing keyboard if there is none.
|
// Removing keyboard if there is none.
|
||||||
msgConfig := tgbotapi.NewMessage(cid, ">")
|
msgConfig := tgbotapi.NewMessage(cid, ">")
|
||||||
msgConfig.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
msgConfig.ReplyMarkup = NewReply().
|
||||||
ch[1] = msgConfig
|
WithRemove(true).
|
||||||
|
ToApi()
|
||||||
|
ret = append(ret, &SendConfig{Message: &msgConfig})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range ch {
|
return ret, nil
|
||||||
if m != nil {
|
|
||||||
msg, err := bot.Api.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
return msgs, err
|
|
||||||
}
|
|
||||||
msgs = append(msgs, &msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgs, nil
|
|
||||||
}
|
}
|
||||||
|
|
36
tg/send.go
36
tg/send.go
|
@ -1,11 +1,43 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
|
import (
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageId int64
|
||||||
|
type Image any
|
||||||
|
|
||||||
// Implementing the interface lets the
|
// Implementing the interface lets the
|
||||||
// value to be sent.
|
// value to be sent.
|
||||||
type Sendable interface {
|
type Sendable interface {
|
||||||
Send(SessionId, *Bot) (*Message, error)
|
SendConfig(SessionId, *Bot) (*SendConfig, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Renderable interface {
|
type Renderable interface {
|
||||||
Render(SessionId, *Bot) ([]*Message, error)
|
Render(SessionId, *Bot) ([]*SendConfig, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The type is used as an endpoint to send messages
|
||||||
|
// via bot.Send .
|
||||||
|
type SendConfig struct {
|
||||||
|
// Simple message with text.
|
||||||
|
// to add text use lower image
|
||||||
|
// or see the ParseMode for tgbotapi .
|
||||||
|
Message *tgbotapi.MessageConfig
|
||||||
|
|
||||||
|
// The image to be sent.
|
||||||
|
Image *tgbotapi.PhotoConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to the bot.Api.Send format.
|
||||||
|
func (config *SendConfig) ToApi() tgbotapi.Chattable {
|
||||||
|
if config.Message != nil {
|
||||||
|
return *config.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Image != nil {
|
||||||
|
return *config.Image
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue