Writing a telegram bot in R (part 3): How to add keyboard support to a bot

This is the third article in the series "Writing a telegram bot in the R language". In previous publications, we learned how to create a telegram bot, send messages through it, added commands and message filters to the bot. Therefore, before starting to read this article, I highly recommend that you familiarize yourself with the previous ones , because here I will not stop on the bases of bot building described earlier.



In this article, we will improve the usability of our bot by adding a keyboard, which will make the bot interface intuitive and easy to use.





All articles from the series "Writing a telegram bot in the R language"



  1. We create a bot and send messages to telegram using it
  2. Add command support and message filters to the bot
  3. How to add keyboard support to your bot
  4. Building a consistent, logical dialogue with the bot
  5. Bot user rights management


Content



If you are interested in data analysis, you may be interested in my telegram and youtube channels. Most of the content of which is devoted to the R language.



  1. What types of keyboards does the telegram bot support?
  2. Reply keyboard
  3. Inline

    3.1. InLine

    3.2. ,

    3.3. , - habr.com




telegram.bot :



  • Reply — , , . , , .
  • Inline — . , , , . CallbackQueryHandler.


, sendMessage(), reply_markup.



.



Reply



, .



Reply
bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Create Custom Keyboard
text <- "Aren't those custom keyboards cool?"
RKM <- ReplyKeyboardMarkup(
  keyboard = list(
    list(KeyboardButton("Yes, they certainly are!")),
    list(KeyboardButton("I'm not quite sure")),
    list(KeyboardButton("No..."))
  ),
  resize_keyboard = FALSE,
  one_time_keyboard = TRUE
)

# Send Custom Keyboard
bot$sendMessage(chat_id, text, reply_markup = RKM)


telegram.bot. ReplyKeyboardMarkup(), , KeyboardButton().



ReplyKeyboardMarkup() , ? , , , .. .



resize_keyboard , one_time_keyboard .



, 3 :



  • ID — ID


1: Reply
library(telegram.bot)

#    Updater
updater <- Updater('  ')

#  
##    
start <- function(bot, update) {

  #  
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton(" ID")),
      list(KeyboardButton(" ")),
      list(KeyboardButton(" "))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
  )

  #  
  bot$sendMessage(update$message$chat_id,
                  text = ' ', 
                  reply_markup = RKM)

}

##   id 
chat_id <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0(" id  : ", update$message$chat_id),
                  parse_mode = "Markdown")

}

##   
my_name <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("  ", update$message$from$first_name),
                  parse_mode = "Markdown")

}

##   
my_username <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("  ", update$message$from$username),
                  parse_mode = "Markdown")

}

#  
##     ID
MessageFilters$chat_id <- BaseFilter(function(message) {

  #   
  message$text == " ID"

}
)

##     
MessageFilters$name <- BaseFilter(function(message) {

  #   
  message$text == " "

}
)

##     
MessageFilters$username <- BaseFilter(function(message) {

  #   
  message$text == " "
)

#  
h_start    <- CommandHandler('start', start)
h_chat_id  <- MessageHandler(chat_id, filters = MessageFilters$chat_id)
h_name     <- MessageHandler(my_name, filters = MessageFilters$name)
h_username <- MessageHandler(my_username, filters = MessageFilters$username)

#    
updater <- updater + 
            h_start +
            h_chat_id +
            h_name +
            h_username

#   
updater$start_polling()


, ' ' , BotFather ( ).

/start, .. .





, , , , .



4 :



  • start —
  • chat_id —
  • my_name —
  • my_username —


MessageFilters 3 , :



  • chat_id — " ID"
  • name — " "
  • username — " "


4 , .



#  
h_start    <- CommandHandler('start', start)
h_chat_id  <- MessageHandler(chat_id, filters = MessageFilters$chat_id)
h_name     <- MessageHandler(my_name, filters = MessageFilters$name)
h_username <- MessageHandler(my_username, filters = MessageFilters$username)


start() ReplyKeyboardMarkup().



RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton(" ID")),
      list(KeyboardButton(" ")),
      list(KeyboardButton(" "))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)


, , . .. , , :



RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
          KeyboardButton(" ID"),
          KeyboardButton(" "),
          KeyboardButton(" ")
     )
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)




sendMessage(), reply_markup.



  bot$sendMessage(update$message$chat_id,
                  text = ' ', 
                  reply_markup = RKM)


Inline



, Inline . .



, Inline .



Inline answerCallbackQuery(), telegram, Inline .



Inline , CallbackQueryHandler().



Inline telegram.bot.



Inline
# Initialize bot
bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Create Inline Keyboard
text <- "Could you type their phone number, please?"
IKM <- InlineKeyboardMarkup(
  inline_keyboard = list(
    list(
      InlineKeyboardButton(1),
      InlineKeyboardButton(2),
      InlineKeyboardButton(3)
    ),
    list(
      InlineKeyboardButton(4),
      InlineKeyboardButton(5),
      InlineKeyboardButton(6)
    ),
    list(
      InlineKeyboardButton(7),
      InlineKeyboardButton(8),
      InlineKeyboardButton(9)
    ),
    list(
      InlineKeyboardButton("*"),
      InlineKeyboardButton(0),
      InlineKeyboardButton("#")
    )
  )
)

# Send Inline Keyboard
bot$sendMessage(chat_id, text, reply_markup = IKM)


Inline InlineKeyboardMarkup(), , Reply . InlineKeyboardMarkup() , Inline , InlineKeyboardButton().



Inline - callback_data, - HTML , url.



, Inline , .



Inline .



InLine



covid-19. /test, , .



2: Inline
library(telegram.bot)

#    Updater
updater <- Updater('  ')

#    InLine 
test <- function(bot, update) {

  #  InLine 
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("", callback_data = 'yes'),
        InlineKeyboardButton("", callback_data = 'no')
      )
    )
  )

  #    
  bot$sendMessage(update$message$chat_id, 
                  text = "  ?", 
                  reply_markup = IKM)
}

#     
answer_cb <- function(bot, update) {

  #    
  data <- update$callback_query$data

  #   ,  
  uname <- update$effective_user()$first_name

  #  
  if ( data == 'no' ) {

    msg <- paste0(uname, ", ,    covid-19 .")

  } else {

    msg <- paste0(uname, ",      covid-19 .")

  }

  #  
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  #  ,     
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

#  
inline_h      <- CommandHandler('test', test)
query_handler <- CallbackQueryHandler(answer_cb)

#    
updater <- updater + inline_h + query_handler

#  
updater$start_polling()


, ' ' , BotFather ( ).

:



:



  • test — Inline
  • answer_cb — .


, callback_data, . update$callback_query$data, answer_cb.



Inline , answer_cb : CallbackQueryHandler(answer_cb). Inline . CallbackQueryHandler :



  • callback
  • pattern — , callback_data.


pattern :



3: Inline
library(telegram.bot)

#    Updater
updater <- Updater('  ')

#    InLine 
test <- function(bot, update) {  

  #  InLine 
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("", callback_data = 'yes'),
        InlineKeyboardButton("", callback_data = 'no')
      )
    )
  )

  #    
  bot$sendMessage(update$message$chat_id, 
                  text = "  ?", 
                  reply_markup = IKM)
}

#      
answer_cb_yes <- function(bot, update) {

  #   ,  
  uname <- update$effective_user()$first_name

  #  
  msg <- paste0(uname, ",      covid-19 .")

  #  
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  #  ,     
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

#      
answer_cb_no <- function(bot, update) {

  #   ,  
  uname <- update$effective_user()$first_name

  msg <- paste0(uname, ", ,    covid-19 .")

  #  
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  #  ,     
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

#  
inline_h          <- CommandHandler('test', test)
query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')

#    
updater <- updater + 
            inline_h + 
            query_handler_yes +
            query_handler_no

#  
updater$start_polling()


, ' ' , BotFather ( ).

2 , .. , , pattern, :



query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')


answer_cb bot$answerCallbackQuery(callback_query_id = update$callback_query$id), , inline .



,



, .



. /start , "". Inline , , . , .



:





4: ,
library(telegram.bot)
library(httr)
library(stringr)

#    Updater
updater <- Updater('  ')

#  
##     
start <- function(bot, update) {

  #  
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  #  
  bot$sendMessage(update$message$chat_id,
                  text = ' ', 
                  reply_markup = RKM)

}

##   Inine 
weather <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = '', callback_data = 'New York,us'),
        InlineKeyboardButton(text = '-', callback_data = 'Saint Petersburg'),
        InlineKeyboardButton(text = '-', callback_data = 'New York')
      ),
      list(
        InlineKeyboardButton(text = '', callback_data = 'Yekaterinburg,ru'),
        InlineKeyboardButton(text = '', callback_data = 'Berlin,de'),
        InlineKeyboardButton(text = '', callback_data = 'Paris,fr')
      ),
      list(
        InlineKeyboardButton(text = '', callback_data = 'Rome,it'),
        InlineKeyboardButton(text = '', callback_data = 'Odessa,ua'),
        InlineKeyboardButton(text = '', callback_data = 'Kyiv,fr')
      ),
      list(
        InlineKeyboardButton(text = '', callback_data = 'Tokyo'),
        InlineKeyboardButton(text = '', callback_data = 'Amsterdam,nl'),
        InlineKeyboardButton(text = '', callback_data = 'Washington,us')
      )
    )
  )

  # Send Inline Keyboard
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = " ", 
                  reply_markup = IKM)
}

#    
answer_cb <- function(bot, update) {

  #    
  city <- update$callback_query$data

  #  
  ans <- GET('https://api.openweathermap.org/data/2.5/weather', 
             query = list(q     = city,
                          lang  = 'ru',
                          units = 'metric',
                          appid = '4776568ccea136ffe4cda9f1969af340')) 

  #  
  result <- content(ans)

  #  
  msg <- str_glue("{result$name} :\n",
                  " : {result$main$temp}\n",
                  " : {result$wind$speed}\n",
                  ": {result$weather[[1]]$description}")

  #    
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = msg)

  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

#  
##    
MessageFilters$weather <- BaseFilter(function(message) {

  #   
  message$text == ""

}
)

#  
h_start         <- CommandHandler('start', start)
h_weather       <- MessageHandler(weather, filters = MessageFilters$weather)
h_query_handler <- CallbackQueryHandler(answer_cb)

#    
updater <- updater + 
              h_start +
              h_weather +
              h_query_handler

#  
updater$start_polling()


, ' ' , BotFather ( ).

:



:



3 , :



  • start
  • weather — Inline
  • answer_cb — , API , .


start /start, CommandHandler('start', start).



weather :



#  
##    
MessageFilters$weather <- BaseFilter(function(message) {

  #   
  message$text == ""

}
)


: MessageHandler(weather, filters = MessageFilters$weather).



, answer_cb Inline , : CallbackQueryHandler(answer_cb).



answer_cb, city: city <- update$callback_query$data. API , , answerCallbackQuery , , , Inline .



, - habr.com.



, , Inline .



, /start. 6 , , 5 .



, , habR, R.



habR github, devtools. .



install.packages('devtools')
devtools::install_github('selesnow/habR')


:



5:
library(telegram.bot)
library(habR)

#    Updater
updater <- Updater('  ')

#  
##     
start <- function(bot, update) {

  #  
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton(" ")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  #  
  bot$sendMessage(update$message$chat_id,
                  text = ' ', 
                  reply_markup = RKM)

}

##   Inine 
habs <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'R', callback_data = 'R'),
        InlineKeyboardButton(text = 'Data Mining', callback_data = 'data_mining'),
        InlineKeyboardButton(text = 'Data Engineering', callback_data = 'data_engineering')
      ),
      list(
        InlineKeyboardButton(text = 'Big Data', callback_data = 'bigdata'),
        InlineKeyboardButton(text = 'Python', callback_data = 'python'),
        InlineKeyboardButton(text = ' ', callback_data = 'data_visualization')
      )
    )
  )

  # Send Inline Keyboard
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = " ", 
                  reply_markup = IKM)
}

#    
answer_cb <- function(bot, update) {

  #    
  hub <- update$callback_query$data

  #   ,     
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id, 
                          text = '  ,  ') 

  #   ,       
  mid <- bot$sendMessage(chat_id = update$from_chat_id(),
                         text    = "   ,      ")

  #  
  posts <- head(habr_hub_posts(hub, 1), 5)

  #    ,   
  bot$deleteMessage(update$from_chat_id(), mid$message_id) 

  #   
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  #  
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

  #    
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = paste0("5      ", hub),
                  reply_markup = IKM)

}

#  
##    
MessageFilters$hubs <- BaseFilter(function(message) {

  #   
  message$text == " "

}
)

#  
h_start         <- CommandHandler('start', start)
h_hubs          <- MessageHandler(habs, filters = MessageFilters$hubs)
h_query_handler <- CallbackQueryHandler(answer_cb)

#    
updater <- updater + 
  h_start +
  h_hubs  +
  h_query_handler

#  
updater$start_polling()


, ' ' , BotFather ( ).

:



, habs:



##   Inine 
habs <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'R', callback_data = 'r'),
        InlineKeyboardButton(text = 'Data Mining', callback_data = 'data_mining'),
        InlineKeyboardButton(text = 'Data Engineering', callback_data = 'data_engineering')
      ),
      list(
        InlineKeyboardButton(text = 'Big Data', callback_data = 'bigdata'),
        InlineKeyboardButton(text = 'Python', callback_data = 'python'),
        InlineKeyboardButton(text = ' ', callback_data = 'data_visualization')
      )
    )
  )

  # Send Inline Keyboard
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = " ", 
                  reply_markup = IKM)
}


habr_hub_posts(), habR. , , 20 . head() 5 , .



  #  
  posts <- head(habr_hub_posts(hub, 1), 5)


, Inline lapply().



  #   
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  #  
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )


posts$title[x], url : url = posts$link[x].



, , .





, , , . .



, .




All Articles