Implemented rendering also for the inline keyboards.
This commit is contained in:
parent
c537ccdec1
commit
6dd954e8ad
9 changed files with 159 additions and 45 deletions
|
@ -8,8 +8,18 @@ package behx
|
|||
type Behaviour struct {
|
||||
Start Action
|
||||
Screens ScreenMap
|
||||
Keyboards KeyboardMap
|
||||
}
|
||||
|
||||
func NewBehaviour(
|
||||
start Action,
|
||||
screens ScreenMap,
|
||||
keyboards KeyboardMap,
|
||||
) *Behaviour {
|
||||
return &Behaviour{
|
||||
start, screens, keyboards,
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the screen exists in the behaviour.
|
||||
func (beh *Behaviour) ScreenExists(id ScreenId) bool {
|
||||
|
|
|
@ -2,6 +2,7 @@ package behx
|
|||
|
||||
import (
|
||||
apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"log"
|
||||
)
|
||||
|
||||
// The wrapper around Telegram API.
|
||||
|
@ -66,7 +67,10 @@ func (bot *Bot) Run() error {
|
|||
}
|
||||
|
||||
screen := bot.Screens[session.CurrentScreenId]
|
||||
screen.Render(ctx)
|
||||
err := screen.Render(ctx)
|
||||
if err != nil {
|
||||
log.Println("screen rendering:", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -6,7 +6,9 @@ import (
|
|||
|
||||
// The type wraps Telegram API's button to provide Action functionality.
|
||||
type Button struct {
|
||||
apix.KeyboardButton
|
||||
Text string
|
||||
Data string
|
||||
Url string
|
||||
Action Action
|
||||
}
|
||||
|
||||
|
@ -18,11 +20,45 @@ type ButtonRow []*Button
|
|||
// Returns new button with specified text and action.
|
||||
func NewButton(text string, action Action) *Button {
|
||||
return &Button{
|
||||
KeyboardButton: apix.NewKeyboardButton(text),
|
||||
Text: text,
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
func NewButtonData(text string, data string, action Action) *Button {
|
||||
return &Button{
|
||||
Text: text,
|
||||
Data: data,
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
func NewButtonUrl(text string, url string, action Action) *Button {
|
||||
return &Button{
|
||||
Text: text,
|
||||
Url: url,
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
func (btn *Button) ToTelegram() apix.KeyboardButton {
|
||||
return apix.NewKeyboardButton(btn.Text)
|
||||
}
|
||||
|
||||
func (btn *Button) ToTelegramInline() apix.InlineKeyboardButton {
|
||||
if btn.Data != "" {
|
||||
return apix.NewInlineKeyboardButtonData(btn.Text, btn.Data)
|
||||
}
|
||||
|
||||
if btn.Url != "" {
|
||||
return apix.NewInlineKeyboardButtonURL(btn.Text, btn.Url)
|
||||
}
|
||||
|
||||
// If no match then return the data one with data the same as the text.
|
||||
return apix.NewInlineKeyboardButtonData(btn.Text, btn.Text)
|
||||
}
|
||||
|
||||
|
||||
func NewButtonRow(btns ...*Button) ButtonRow {
|
||||
return btns
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ func (c *Context) ChangeScreen(screenId ScreenId) error {
|
|||
|
||||
// Sends to the user specified text.
|
||||
func (c *Context) Send(text string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,5 +7,7 @@ import (
|
|||
var (
|
||||
ScreenNotExistErr = errors.New("screen does not exist")
|
||||
SessionNotExistErr = errors.New("session does not exist")
|
||||
KeyboardNotExistErr = errors.New("keyboard does not exist")
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -17,12 +17,16 @@ var otherKeyboard = tgbotapi.NewReplyKeyboard(
|
|||
),
|
||||
)*/
|
||||
|
||||
type KeyboardId string
|
||||
|
||||
// The type represents reply keyboard which
|
||||
// is supposed to be showed on a Screen.
|
||||
type Keyboard struct {
|
||||
Rows []ButtonRow
|
||||
}
|
||||
|
||||
type KeyboardMap map[KeyboardId] *Keyboard
|
||||
|
||||
// Return the new reply keyboard with rows as specified.
|
||||
func NewKeyboard(rows ...ButtonRow) *Keyboard {
|
||||
return &Keyboard{
|
||||
|
@ -36,7 +40,7 @@ func (kbd *Keyboard) ToTelegram() apix.ReplyKeyboardMarkup {
|
|||
for _, row := range kbd.Rows {
|
||||
buttons := []apix.KeyboardButton{}
|
||||
for _, button := range row {
|
||||
buttons = append(buttons, apix.NewKeyboardButton(button.Text))
|
||||
buttons = append(buttons, button.ToTelegram())
|
||||
}
|
||||
rows = append(rows, buttons)
|
||||
}
|
||||
|
@ -44,6 +48,19 @@ func (kbd *Keyboard) ToTelegram() apix.ReplyKeyboardMarkup {
|
|||
return apix.NewReplyKeyboard(rows...)
|
||||
}
|
||||
|
||||
func (kbd *Keyboard) ToTelegramInline() apix.InlineKeyboardMarkup {
|
||||
rows := [][]apix.InlineKeyboardButton{}
|
||||
for _, row := range kbd.Rows {
|
||||
buttons := []apix.InlineKeyboardButton{}
|
||||
for _, button := range row {
|
||||
buttons = append(buttons, button.ToTelegramInline())
|
||||
}
|
||||
rows = append(rows, buttons)
|
||||
}
|
||||
|
||||
return apix.NewInlineKeyboardMarkup(rows...)
|
||||
}
|
||||
|
||||
// Returns the map of buttons. Used to define the Action.
|
||||
func (kbd *Keyboard) buttonMap() ButtonMap {
|
||||
ret := make(ButtonMap)
|
||||
|
|
|
@ -16,20 +16,23 @@ type ScreenText string
|
|||
type Screen struct {
|
||||
// Text to be sent to the user when changing to the screen.
|
||||
Text ScreenText
|
||||
// Keyboard to be displayed on the screen.
|
||||
Keyboard *Keyboard
|
||||
|
||||
// The keyboard to be sent in the message part.
|
||||
InlineKeyboard *Keyboard
|
||||
InlineKeyboardId KeyboardId
|
||||
|
||||
// Keyboard to be displayed on the screen.
|
||||
KeyboardId KeyboardId
|
||||
}
|
||||
|
||||
// Map structure for the screens.
|
||||
type ScreenMap map[ScreenId] *Screen
|
||||
|
||||
// Returns the new screen with specified Text and Keyboard.
|
||||
func NewScreen(text ScreenText, kbd *Keyboard) *Screen {
|
||||
func NewScreen(text ScreenText, ikbd KeyboardId, kbd KeyboardId) *Screen {
|
||||
return &Screen {
|
||||
Text: text,
|
||||
Keyboard: kbd,
|
||||
InlineKeyboardId: ikbd,
|
||||
KeyboardId: kbd,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,25 +42,40 @@ func (st ScreenText) String() string {
|
|||
}
|
||||
|
||||
// Renders output of the screen to the side of the user.
|
||||
func (s *Screen) Render(c *Context) {
|
||||
func (s *Screen) Render(c *Context) error {
|
||||
id := c.S.Id.ToTelegram()
|
||||
|
||||
msg := apix.NewMessage(id, s.Text.String())
|
||||
|
||||
// First sending the inline keyboard.
|
||||
if s.InlineKeyboard != nil {
|
||||
msg.ReplyMarkup = s.InlineKeyboard.ToTelegram()
|
||||
if _, err := c.B.Send(msg) ; err != nil {
|
||||
panic(err)
|
||||
if s.InlineKeyboardId != "" {
|
||||
kbd, ok := c.B.Keyboards[s.InlineKeyboardId]
|
||||
if !ok {
|
||||
return KeyboardNotExistErr
|
||||
}
|
||||
msg.ReplyMarkup = kbd.ToTelegramInline()
|
||||
}
|
||||
|
||||
// Then sending the screen one.
|
||||
if s.Keyboard != nil {
|
||||
msg = apix.NewMessage(id, "check")
|
||||
msg.ReplyMarkup = s.Keyboard.ToTelegram()
|
||||
if _, err := c.B.Send(msg) ; err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err := c.B.Send(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.KeyboardId != "" {
|
||||
msg = apix.NewMessage(id, ">")
|
||||
|
||||
kbd, ok := c.B.Keyboards[s.KeyboardId]
|
||||
if !ok {
|
||||
return KeyboardNotExistErr
|
||||
}
|
||||
|
||||
msg.ReplyMarkup = kbd.ToTelegram()
|
||||
if _, err := c.B.Send(msg) ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ type Session struct {
|
|||
Id SessionId
|
||||
CurrentScreenId ScreenId
|
||||
PreviousScreenId ScreenId
|
||||
KeyboardId KeyboardId
|
||||
}
|
||||
|
||||
// The type represents map of sessions using
|
||||
|
|
|
@ -8,34 +8,61 @@ import (
|
|||
"boteval/src/behx"
|
||||
)
|
||||
|
||||
var startScreen = behx.NewScreen(
|
||||
"Hello, World!",
|
||||
behx.NewKeyboard(
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton(
|
||||
"PRESS ME",
|
||||
behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed the button!")
|
||||
}),
|
||||
),
|
||||
behx.NewButton("PRESS ME 2", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed another button!")
|
||||
})),
|
||||
),
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton("PRESS ME 3", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed third button!")
|
||||
})),
|
||||
var rootKbd = behx.NewKeyboard(
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton(
|
||||
"PRESS ME",
|
||||
behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed the button!")
|
||||
}),
|
||||
),
|
||||
behx.NewButton("PRESS ME 2", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed another button!")
|
||||
})),
|
||||
),
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton("PRESS ME 3", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("pressed third button!")
|
||||
})),
|
||||
),
|
||||
)
|
||||
|
||||
var behaviour = &behx.Behaviour{
|
||||
Start: behx.NewScreenChange("start"),
|
||||
Screens: behx.ScreenMap{
|
||||
var inlineKbd = behx.NewKeyboard(
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton(
|
||||
"INLINE PRESS ME",
|
||||
behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("INLINE pressed the button!")
|
||||
}),
|
||||
),
|
||||
behx.NewButton("INLINE PRESS ME 2", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("INLINE pressed another button!")
|
||||
})),
|
||||
),
|
||||
behx.NewButtonRow(
|
||||
behx.NewButton("INLINE PRESS ME 3", behx.NewCustomAction(func(c *behx.Context){
|
||||
log.Println("INLINE pressed third button!")
|
||||
})),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
var startScreen = behx.NewScreen(
|
||||
"Hello, World!",
|
||||
"inline",
|
||||
"root",
|
||||
)
|
||||
|
||||
var behaviour = behx.NewBehaviour(
|
||||
behx.NewScreenChange("start"),
|
||||
behx.ScreenMap{
|
||||
"start": startScreen,
|
||||
},
|
||||
}
|
||||
behx.KeyboardMap{
|
||||
"root": rootKbd,
|
||||
"inline": inlineKbd,
|
||||
},
|
||||
)
|
||||
|
||||
func main() {
|
||||
token := os.Getenv("BOT_TOKEN")
|
||||
|
|
Loading…
Reference in a new issue