button.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package tg
  2. import (
  3. apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
  4. "fmt"
  5. "crypto/rand"
  6. "encoding/base64"
  7. )
  8. // The type wraps Telegram API's button to provide Action functionality.
  9. type Button struct {
  10. Text string
  11. Data string
  12. Url string
  13. SendLocation bool
  14. Action Action
  15. }
  16. type ButtonMap map[string]Button
  17. // Returns the only location button in the map.
  18. func (btnMap ButtonMap) LocationButton() *Button {
  19. for _, btn := range btnMap {
  20. if btn.SendLocation {
  21. return btn
  22. }
  23. }
  24. return nil
  25. }
  26. // Represents the reply button row.
  27. type ButtonRow []*Button
  28. // Returns new button with the specified text and no action.
  29. func Buttonf(format string, v ...any) Button {
  30. return &Button{
  31. Text: fmt.Sprintf(format, v...),
  32. }
  33. }
  34. // Randomize buttons data to make the key unique.
  35. func (btn Button) Rand() Button {
  36. rData := make([]byte, 8)
  37. rand.Read(rData)
  38. data := make([]byte, base64.StdEncoding.EncodedLen(len(rData)))
  39. base64.StdEncoding.Encode(data, rData)
  40. btn.Data = string(data)
  41. return btn
  42. }
  43. // Set the URL for the button. Only for inline buttons.
  44. func (btn Button) WithUrl(format string, v ...any) Button {
  45. btn.Url = fmt.Sprintf(format, v...)
  46. return btn
  47. }
  48. // Set the action when pressing the button.
  49. // By default is nil and does nothing.
  50. func (btn Button) WithAction(a Action) Button {
  51. btn.Action = a
  52. return btn
  53. }
  54. func (btn Button) WithData(dat string) Button {
  55. btn.Data = dat
  56. return btn
  57. }
  58. // Sets whether the button must send owner's location.
  59. func (btn Button) WithSendLocation(ok bool) Button {
  60. btn.SendLocation = ok
  61. return btn
  62. }
  63. func (btn Button) Go(pth Path, args ...any) Button {
  64. return btn.WithAction(ScreenGo{
  65. Path: pth,
  66. Args: args,
  67. })
  68. }
  69. func (btn Button) ToTelegram() apix.KeyboardButton {
  70. ret := apix.NewKeyboardButton(btn.Text)
  71. if btn.SendLocation {
  72. ret.RequestLocation = true
  73. }
  74. return ret
  75. }
  76. func (btn Button) ToTelegramInline() apix.InlineKeyboardButton {
  77. if btn.Data != "" {
  78. return apix.NewInlineKeyboardButtonData(btn.Text, btn.Data)
  79. }
  80. if btn.Url != "" {
  81. return apix.NewInlineKeyboardButtonURL(btn.Text, btn.Url)
  82. }
  83. // If no match then return the data one with data the same as the text.
  84. return apix.NewInlineKeyboardButtonData(btn.Text, btn.Text)
  85. }
  86. // Return the key of the button to identify it by messages and callbacks.
  87. func (btn Button) Key() string {
  88. if btn == nil {
  89. return ""
  90. }
  91. if btn.Data != "" {
  92. return btn.Data
  93. }
  94. // If no match then return the data one with data the same as the text.
  95. return btn.Text
  96. }
  97. func NewButtonRow(btns ...*Button) ButtonRow {
  98. return btns
  99. }