package tg import ( tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) // The type represents keyboard to be emdedded // into the messages (inline in Telegram terms). type Inline struct { Keyboard } // Convert the inline keyboard to markup for the tgbotapi. func (kbd Inline) ToAPI() tgbotapi.InlineKeyboardMarkup { rows := [][]tgbotapi.InlineKeyboardButton{} for _, row := range kbd.Rows { if row == nil { continue } buttons := []tgbotapi.InlineKeyboardButton{} for _, button := range row { if !button.Valid { continue } buttons = append(buttons, button.ToTelegramInline()) } rows = append(rows, buttons) } return tgbotapi.NewInlineKeyboardMarkup(rows...) } // The type implements message with an inline keyboard. type InlineCompo struct { MessageCompo Inline } // Implementing the Sendable interface. func (compo *InlineCompo) SendConfig( sid SessionID, bot *Bot, ) (SendConfig) { sendConfig := compo.MessageCompo.SendConfig(sid, bot) msg := sendConfig.Chattable.(tgbotapi.MessageConfig) if len(compo.Inline.Rows) > 0 { msg.ReplyMarkup = compo.Inline.ToAPI() } sendConfig.Chattable = msg return sendConfig } // Update the component on the client side. // Requires exactly the pointer but not the value // cause it changes insides of the structure. func (compo *InlineCompo) Update(c Context) error { if compo.Message != nil { var edit tgbotapi.Chattable markup := compo.Inline.ToAPI() ln := len(markup.InlineKeyboard) if ln == 0 || compo.Inline.Rows == nil { edit = tgbotapi.NewEditMessageText( c.SessionID().ToAPI(), compo.Message.MessageID, compo.Text, ) } else { edit = tgbotapi.NewEditMessageTextAndMarkup( c.SessionID().ToAPI(), compo.Message.MessageID, compo.Text, markup, ) } msg, err := c.Bot().API().Send(edit) if err != nil { return err } compo.Message = &msg } return nil } // Implementing the Filterer interface. func (compo *InlineCompo) Filter(u Update) bool { if u.CallbackQuery == nil { return true } if u.CallbackQuery.Message.MessageID != compo.Message.MessageID { return true } return false } // Implementing the Server interface. func (compo *InlineCompo) Serve(c Context) { for u := range c.Input() { compo.OnOneUpdate(c, u) } } func (compo *InlineCompo) OnOneUpdate(c Context, u Update) error { var act Action btns := compo.ButtonMap() cb := tgbotapi.NewCallback( u.CallbackQuery.ID, u.CallbackQuery.Data, ) data := u.CallbackQuery.Data _, err := c.Bot().API().Request(cb) if err != nil { return err } btn, ok := btns[data] if !ok { return nil } if btn.Action != nil { act = btn.Action } else if compo.Action != nil { act = compo.Action } c.WithUpdate(u).Run(act) return nil }