Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

To trzeci artykuł z serii „Tworzymy bota Telegram w języku R”. W poprzednich publikacjach nauczyliśmy się tworzyć bota Telegram, wysyłać przez niego wiadomości, dodawaliśmy komendy i filtry wiadomości. Dlatego przed przystąpieniem do lektury tego artykułu zdecydowanie polecam zapoznać się z poprzednimi, ponieważ tutaj nie będę się zatrzymywać na wcześniej opisanych podstawach budowy bota.

W tym artykule poprawimy użyteczność naszego bota poprzez dodanie klawiatury, która uczyni interfejs bota intuicyjnie zrozumiałym i prostym w użyciu.

Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Wszystkie artykuły z serii „Tworzymy bota Telegram w języku R”

  1. Tworzymy bota i wysyłamy z jego pomocą wiadomości w Telegramie
  2. Dodajemy wsparcie dla komend i filtry wiadomości
  3. Jak dodać wsparcie dla klawiatury do bota

Spis treści

Jeśli interesujesz się analizą danych, to mogą Cię zainteresować moje telegram i youtube kanały. Większość zawartości poświęcona jest językowi R.

  1. Jakie typy klawiatur wspiera bot Telegram
  2. Klawiatura Reply
  3. Klawiatura Inline
    3.1. Przykład najprostszej aplikacji bota z wsparciem dla przycisków Inline
    3.2. Przykład bota, który informuje o aktualnej pogodzie dla wybranego miasta
    3.3. Przykład bota, który wyświetla listę najnowszych artykułów z linkami do wskazanego Habu z habr.com
  4. Podsumowanie

Jakie typy klawiatur wspiera bot Telegram

W momencie pisania artykułu telegram.bot umożliwia Ci stworzenie klawiatur dwóch typów:

  • Reply — Podstawowa, normalna klawiatura, która znajduje się pod panelem wprowadzania tekstu wiadomości. Taka klawiatura po prostu wysyła do bota tekstową wiadomość i jako tekst wysyła ten, który jest napisany na samej przycisku.
  • Inline — Klawiatura przypisana do konkretnej wiadomości bota. Ta klawiatura przesyła do bota dane związane z naciśniętym przyciskiem, które mogą różnić się od tekstu napisanego na przycisku. Takie przyciski są przetwarzane za pośrednictwem CallbackQueryHandler.

Aby bot otworzył klawiaturę, musisz podczas wysyłania wiadomości przez metodę sendMessage(), przekazać wcześniej utworzoną klawiaturę jako argument reply_markup.

Poniżej omówimy kilka przykładów.

Klawiatura Reply

Jak już wcześniej pisałem, to główna klawiatura sterująca botem.

Przykład tworzenia klawiatury Reply z oficjalnej dokumentacji

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

# Tworzenie niestandardowej klawiatury
text <- "Czy te niestandardowe klawiatury nie są fajne?"
RKM <- ReplyKeyboardMarkup(
  keyboard = list(
    list(KeyboardButton("Tak, z pewnością!")),
    list(KeyboardButton("Nie jestem pewien")),
    list(KeyboardButton("Nie..."))
  ),
  resize_keyboard = FALSE,
  one_time_keyboard = TRUE
)

# Wysyłanie niestandardowej klawiatury
bot$sendMessage(chat_id, text, reply_markup = RKM)

Powyżej znajduje się przykład z oficjalnej dokumentacji pakietu telegram.bot. Do tworzenia klawiatury używana jest funkcja ReplyKeyboardMarkup(), która z kolei przyjmuje listę list przycisków, które są tworzone przez funkcję KeyboardButton().

Dlaczego w ReplyKeyboardMarkup() należy przekazywać nie tylko listę, ale listę list? Chodzi o to, że przekazujesz główną listę, a w niej oddzielnymi listami definiujesz każdy rząd przycisków, ponieważ w jednym rzędzie można umieścić kilka przycisków.

Argument resize_keyboard pozwala automatycznie dopasować optymalny rozmiar przycisków klawiatury, a argument one_time_keyboard pozwala ukryć klawiaturę po każdym naciśnięciu przycisku.

Napiszmy prostego bota, który będzie miał 3 przyciski:

  • Chat ID — Zapytaj o ID czatu dialogu z botem
  • Moje imię — Zapytaj o swoje imię
  • Mój login — Zapytaj o swoją nazwę użytkownika w Telegramie

Kod 1: Prosty bot z klawiaturą Reply

library(telegram.bot)

# Tworzymy instancję klasy Updater
updater <- Updater('TWÓJ TOKEN BOTA')

# Tworzymy metody
## metoda do uruchamiania klawiatury
start <- function(bot, update) {

  # Tworzymy klawiaturę
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("ID czatu")),
      list(KeyboardButton("Moje imię")),
      list(KeyboardButton("Mój login"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
  )

  # Wysyłamy klawiaturę
  bot$sendMessage(update$message$chat_id,
                  text = 'Wybierz komendę', 
                  reply_markup = RKM)

}

## metoda zwracająca ID czatu
chat_id <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("ID czatu tej rozmowy: ", update$message$chat_id),
                  parse_mode = "Markdown")

}

## metoda zwracająca imię
my_name <- function(bot, update) {

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

}

## metoda zwracająca login
my_username <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Twój login to ", update$message$from$username),
                  parse_mode = "Markdown")

}

# Tworzymy filtry
## wiadomości z tekstem ID czatu
MessageFilters$chat_id <- BaseFilter(function(message) {

  # Sprawdzamy tekst wiadomości
  message$text == "ID czatu"

}
)

## wiadomości z tekstem Moje imię
MessageFilters$name <- BaseFilter(function(message) {

  # Sprawdzamy tekst wiadomości
  message$text == "Moje imię"

}
)

## wiadomości z tekstem Mój login
MessageFilters$username <- BaseFilter(function(message) {

  # Sprawdzamy tekst wiadomości
  message$text == "Mój login"
)

# Tworzymy obsługiwacze
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)

# Dodajemy obsługiwacze do menedżera
updater <- updater + 
            h_start +
            h_chat_id +
            h_name +
            h_username

# Uruchamiamy bota 
updater$start_polling()

Uruchom powyższy przykład kodu, wcześniej zastępując ‘TWÓJ TOKEN BOTA’ prawdziwym tokenem, który otrzymałeś podczas tworzenia bota przez BotFather (o tworzeniu bota opowiadałem w pierwszym artykule).

Po uruchomieniu, nadaj botowi polecenie /start, ponieważ to właśnie je zdefiniowaliśmy do uruchamiania klawiatury.

Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Jeśli w tej chwili masz trudności z zrozumieniem powyższego przykładu kodu, z metodami, filtrami i obsługiwaczami, warto wrócić do wcześniejszej artykuł, w której szczegółowo to wszystko opisałem.

Stworzyliśmy 4 metody:

  • start — Uruchomienie klawiatury
  • chat_id — Zapytanie o identyfikator czatu
  • my_name — Zapytanie o swoje imię
  • my_username — Zapytanie o swój login

Do obiektu MessageFilters dodaliśmy 3 filtry wiadomości, według ich tekstu:

  • chat_id — Wiadomości z tekstem "ID czatu"
  • name — Wiadomości z tekstem "Moje imię"
  • username — Wiadomości z tekstem "Mój login"

I stworzono 4 obsługiwaczy, które na podstawie podanych poleceń i filtrów będą wykonywać określone metody.

# создаём обработчики
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)

Sama klawiatura jest tworzona wewnątrz metody start() poleceniem ReplyKeyboardMarkup().

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("ID czatu")),
      list(KeyboardButton("Moje imię")),
      list(KeyboardButton("Mój login"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

W naszym przypadku wszystkie przyciski umieściliśmy jeden pod drugim, ale możemy je umieścić w jednym rzędzie, wprowadzając zmiany w liście list przycisków. Ponieważ jeden rząd w klawiaturze jest tworzony za pomocą zagnieżdżonej listy przycisków, aby wyświetlić nasze przyciski w jednym rzędzie, należy przekształcić część kodu budującego klawiaturę w ten sposób:

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
          KeyboardButton("ID czatu"),
          KeyboardButton("Moje imię"),
          KeyboardButton("Mój login")
     )
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Klawiatura jest wysyłana do czatu za pomocą metody sendMessage(), w argumencie reply_markup.

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

Klawiatura Inline

Jak już wspomniałem, klawiatura Inline jest przypisana do konkretnej wiadomości. Praca z nią jest nieco bardziej skomplikowana niż z główną klawiaturą.

Najpierw musisz dodać do bota metodę do wywoływania klawiatury Inline.

Aby odpowiedzieć na naciśnięcie przycisku Inline, możesz również użyć metody bota answerCallbackQuery(), która może wyświetlić powiadomienie w interfejsie telegramu użytkownikowi, który nacisnął przycisk Inline.

Dane wysłane z przycisku Inline nie są tekstem, dlatego aby je przetworzyć, należy stworzyć specjalny obsługiwacz za pomocą polecenia CallbackQueryHandler().

Kod budowy klawiatury Inline jest przedstawiony w oficjalnej dokumentacji pakietu telegram.bot.

Kod budowy klawiatury Inline z oficjalnej dokumentacji

# 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)

Budowanie klawiatury Inline należy przeprowadzić za pomocą polecenia InlineKeyboardMarkup(), w podobny sposób jak klawiatury Reply. W InlineKeyboardMarkup() należy przekazać listę, list Inline przycisków, każdy przycisk jest tworzony za pomocą funkcji InlineKeyboardButton().

Przycisk Inline może albo przesyłać botowi jakieś dane za pomocą argumentu callback_data, albo otwierać jakąkolwiek stronę HTML, określoną za pomocą argumentu url.

W rezultacie uzyskamy listę, w której każdy element również jest listą przycisków Inline, które należy połączyć w jeden rząd.

Następnie omówimy kilka przykładów botów z przyciskami inline.

Przykład najprostszej aplikacji bota z wsparciem dla przycisków Inline

Na początek napiszemy bota do szybkiego testowania na covid-19. Na komendę /test, wyśle ci klawiaturę z dwoma przyciskami, a w zależności od naciśniętego przycisku wyśle ci wiadomość z wynikami twojego testu.

Kod 2: Najprostszy bot z klawiaturą inline

library(telegram.bot)

# tworzę instancję klasy Updater
updater <- Updater('TOKEN TWOJEGO BOTA')

# metoda do wysyłania klawiatury inline
test <- function(bot, update) {

  # tworzę klawiaturę inline
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Tak", callback_data = 'yes'),
        InlineKeyboardButton("Nie", callback_data = 'no')
      )
    )
  )

  # Wysyłam klawiaturę na czat
  bot$sendMessage(update$message$chat_id,
                  text = "Czy masz koronawirusa?",
                  reply_markup = IKM)
}

# metoda do przetwarzania naciśnięcia przycisku
answer_cb <- function(bot, update) {

  # otrzymane dane z przycisku
  data <- update$callback_query$data

  # uzyskuję imię użytkownika, który nacisnął przycisk
  uname <- update$effective_user()$first_name

  # przetwarzanie wyniku
  if ( data == 'no' ) {

    msg <- paste0(uname, ", gratulacje, twój test na covid-19 jest negatywny.")

  } else {

    msg <- paste0(uname, ", niestety, twój test na covid-19 jest pozytywny.")

  }

  # Wysłanie wiadomości
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # informuję bota, że zapytanie z przycisku zostało przyjęte
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# tworzę obsługiwacze
inline_h      <- CommandHandler('test', test)
query_handler <- CallbackQueryHandler(answer_cb)

# dodaję obsługiwacze do menedżera
updater <- updater + inline_h + query_handler

# uruchamiam bota
updater$start_polling()

Uruchom powyższy przykład kodu, wcześniej zastępując ‘TWÓJ TOKEN BOTA’ prawdziwym tokenem, który otrzymałeś podczas tworzenia bota przez BotFather (o tworzeniu bota opowiadałem w pierwszym artykule).

Wynik:
Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Utworzyliśmy dwie metody:

  • test — Do wysyłania klawiatury inline na czat
  • answer_cb — Do przetwarzania danych wysyłanych z klawiatury.

Dane, które będą wysyłane z każdego przycisku są ustalane w argumencie callback_data, przy tworzeniu przycisku. Otrzymać wysłane z przycisku dane można za pomocą konstrukcji update$callback_query$data, wewnątrz metody answer_cb.

Aby bot reagował na klawiaturę inline, metoda answer_cb jest przetwarzana przez specjalny obsługiwacz: CallbackQueryHandler(answer_cb). Który uruchamia określoną metodę po naciśnięciu przycisku inline. Obsługiwacz CallbackQueryHandler przyjmuje dwa argumenty:

  • callback — metoda, którą należy uruchomić
  • wzorzec — filtr według danych, które są przypisane do przycisku za pomocą argumentu callback_data.

Odpowiednio za pomocą argumentu wzorzec możemy napisać oddzielną metodę na każde naciśnięcie przycisku:

Kod 3: Rozdzielamy metody dla każdego przycisku inline

library(telegram.bot)

# tworzymy instancję klasy Updater
updater <- Updater('TOKEN TWOJEGO BOTA')

# metoda do wysyłania InLine klawiatury
test <- function(bot, update) {  

  # tworzymy InLine klawiaturę
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Tak", callback_data = 'yes'),
        InlineKeyboardButton("Nie", callback_data = 'no')
      )
    )
  )

  # Wysyłamy klawiaturę na czacie
  bot$sendMessage(update$message$chat_id, 
                  text = "Czy jesteś chory na koronawirusa?", 
                  reply_markup = IKM)
}

# metoda do obsługi kliknięcia przycisku Tak
answer_cb_yes <- function(bot, update) {

  # pobieramy imię użytkownika, który kliknął przycisk
  uname <- update$effective_user()$first_name

  # przetwarzanie wyniku
  msg <- paste0(uname, ", niestety twój test na covid-19 jest pozytywny.")

  # Wysłanie wiadomości
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # informujemy bota, że zapytanie z przycisku zostało przyjęte
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# metoda do obsługi kliknięcia przycisku Nie
answer_cb_no <- function(bot, update) {

  # pobieramy imię użytkownika, który kliknął przycisk
  uname <- update$effective_user()$first_name

  msg <- paste0(uname, ", gratulacje, twój test na covid-19 jest negatywny.")

  # Wysłanie wiadomości
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # informujemy bota, że zapytanie z przycisku zostało przyjęte
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

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

# dodajemy obsługiwacze do menedżera
updater <- updater + 
            inline_h + 
            query_handler_yes +
            query_handler_no

# uruchamiamy bota
updater$start_polling()

Uruchom powyższy przykład kodu, wcześniej zastępując ‘TWÓJ TOKEN BOTA’ prawdziwym tokenem, który otrzymałeś podczas tworzenia bota przez BotFather (o tworzeniu bota opowiadałem w pierwszym artykule).

Teraz napisaliśmy 2 oddzielne metody, tj. po jednej metodzie na kliknięcie każdego przycisku oraz użyliśmy argumentu wzorzec, przy tworzeniu ich obsługiwaczy:

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

Kończy się kod metody answer_cb poleceniem bot$answerCallbackQuery(callback_query_id = update$callback_query$id), która informuje bota, że dane z inline klawiatury zostały odebrane.

Przykład bota, który informuje o aktualnej pogodzie dla wybranego miasta

Spróbujmy napisać bota, który pyta o dane dotyczące pogody.

Logika działania będzie następująca. Początkowo komendą /start wywołujesz główną klawiaturę, w której znajduje się tylko jeden przycisk "Pogoda". Po naciśnięciu tego przycisku otrzymujesz wiadomość z InLine klawiaturą, aby wybrać miasto, dla którego chcesz znać aktualną pogodę. Wybierasz jedno z miast i otrzymujesz bieżącą prognozę.

W tym przykładzie kodu użyjemy kilku dodatkowych pakietów:

  • httr — pakiet do obsługi zapytań HTTP, na którym oparta jest praca z każdym API. W naszym przypadku będziemy korzystać z darmowego API openweathermap.org.
  • stringr — pakiet do pracy z tekstem, w naszym przypadku będziemy go używać do tworzenia komunikatu o pogodzie w wybranym mieście.

Kod 4: Bot, który informuje o aktualnej pogodzie w wybranym mieście

library(telegram.bot)
library(httr)
library(stringr)

# Tworzymy instancję klasy Updater
updater <- Updater('TOKEN TWOJEGO BOTA')

# Tworzymy metody
## metoda do uruchomienia głównej klawiatury
start <- function(bot, update) {

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

  # Wysyłamy klawiaturę
  bot$sendMessage(update$message$chat_id,
                  text = 'Wybierz polecenie', 
                  reply_markup = RKM)

}

## Metoda wywołania klawiatury Inline
weather <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'Moskwa', callback_data = 'New York,us'),
        InlineKeyboardButton(text = 'Sankt Petersburg', callback_data = 'Saint Petersburg'),
        InlineKeyboardButton(text = 'Nowy Jork', callback_data = 'New York')
      ),
      list(
        InlineKeyboardButton(text = 'Jekaterynburg', callback_data = 'Yekaterinburg,ru'),
        InlineKeyboardButton(text = 'Berlin', callback_data = 'Berlin,de'),
        InlineKeyboardButton(text = 'Paryż', callback_data = 'Paris,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Rzym', callback_data = 'Rome,it'),
        InlineKeyboardButton(text = 'Odessa', callback_data = 'Odessa,ua'),
        InlineKeyboardButton(text = 'Kijów', callback_data = 'Kyiv,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Tokio', callback_data = 'Tokyo'),
        InlineKeyboardButton(text = 'Amsterdam', callback_data = 'Amsterdam,nl'),
        InlineKeyboardButton(text = 'Waszyngton', callback_data = 'Washington,us')
      )
    )
  )

  # Wyślij klawiaturę Inline
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Wybierz miasto", 
                  reply_markup = IKM)
}

# Metoda do przesyłania informacji o pogodzie
answer_cb <- function(bot, update) {

  # Pobieramy miasto z wiadomości
  city <- update$callback_query$data

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

  # Parsujemy odpowiedź
  result <- content(ans)

  # Formujemy wiadomość
  msg <- str_glue("{result$name} pogoda:n",
                  "Aktualna temperatura: {result$main$temp}n",
                  "Prędkość wiatru: {result$wind$speed}n",
                  "Opis: {result$weather[[1]]$description}")

  # Wysyłamy informację o pogodzie
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = msg)

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

# Tworzymy filtry
## wiadomości z tekstem Pogoda
MessageFilters$weather <- BaseFilter(function(message) {

  # Sprawdzamy tekst wiadomości
  message$text == "Pogoda"

}
)

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

# Dodajemy obsługiwacze do dispatcher
updater <- updater + 
              h_start +
              h_weather +
              h_query_handler

# Uruchamiamy bota
updater$start_polling()

Uruchom powyższy przykład kodu, wcześniej zastępując ‘TWÓJ TOKEN BOTA’ prawdziwym tokenem, który otrzymałeś podczas tworzenia bota przez BotFather (o tworzeniu bota opowiadałem w pierwszym artykule).

W rezultacie nasz bot będzie działał mniej więcej tak:
Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Schematycznie tego bota można zobaczyć tak:
Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Stworzyliśmy 3 metody, dostępne w naszym bocie pogodowym:

  • start — Uruchomienie głównej klawiatury bota
  • weather — Uruchomienie klawiatury inline do wyboru miasta
  • answer_cb — Główna metoda, która na podstawie podanego miasta pobiera w API dane o pogodzie i wysyła je na czat.

Metoda start uruchamiamy za pomocą komendy /start, co realizuje handler CommandHandler('start', start).

Aby uruchomić metodę weather stworzono filtr o tej samej nazwie:

# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {

  # проверяем текст сообщения
  message$text == "Погода"

}
)

I wywołujemy tę metodę następnym handlerem wiadomości: MessageHandler(weather, filters = MessageFilters$weather).

I w końcu nasza główna metoda answer_cb reaguje na naciśnięcie przycisków inline, co realizuje specjalny handler: CallbackQueryHandler(answer_cb).

Wewnątrz metody answer_cb, odczytujemy dane wysłane z klawiatury i zapisujemy je w zmiennej city: city <- update$callback_query$data. Po czym pobieramy z API dane o pogodzie, formatujemy i wysyłamy wiadomość, a na koniec używamy metody answerCallbackQuery aby poinformować bota, że przetworzyliśmy naciśnięcie przycisku inline.

Przykład bota, który wyświetla listę najnowszych artykułów z linkami do wskazanego Habu z habr.com.

Tego bota podaję, aby pokazać Wam, jak wyświetlić przyciski inline, które prowadzą do stron internetowych.

Logika tego bota jest podobna do poprzedniego, najpierw uruchamiamy główną klawiaturę komendą /start. Następnie bot daje nam do wyboru listę 6 hubów, wybieramy interesujący nas hub i otrzymujemy 5 najnowszych publikacji z wybranego Habu.

Jak rozumiecie, w tym przypadku musimy uzyskać listę artykułów, i w tym celu będziemy używać specjalnego pakietu habR, który pozwala na pobieranie artykułów z Habr i pewnych statystyk na ich temat w R.

Zainstalować pakiet habR można tylko z github, do czego potrzebny będzie dodatkowy pakiet devtools. Do instalacji użyj poniższego kodu.

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

Teraz przyjrzyjmy się kodowi opisującemu powyższego bota:

Kod 5: Bot, który wyświetla listę najnowszych artykułów z wybranego Habu

library(telegram.bot)
library(habR)

# Tworzymy instancję klasy Updater
updater <- Updater('TOKEN TWOJEGO BOTA')

# Tworzymy metody
## metoda do uruchomienia głównej klawiatury
start <- function(bot, update) {

  # Tworzymy klawiaturę
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("Lista artykułów")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  # Wysyłamy klawiaturę
  bot$sendMessage(update$message$chat_id,
                  text = 'Wybierz polecenie', 
                  reply_markup = RKM)

}

## Metoda wywołania klawiatury Inline
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 = 'Wizualizacja danych', callback_data = 'data_visualization')
      )
    )
  )

  # Wysyłamy klawiaturę Inline
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Wybierz Hub", 
                  reply_markup = IKM)
}

# metoda do przekazywania prognozy pogody
answer_cb <- function(bot, update) {

  # Pobieramy z wiadomości hub
  hub <- update$callback_query$data

  # Wiadomość informująca, że dane z przycisku zostały odebrane
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id, 
                          text = 'Proszę czekać kilka minut, przetwarzam zapytanie') 

  # Wiadomość informująca, że należy poczekać, aż bot uzyska dane
  mid <- bot$sendMessage(chat_id = update$from_chat_id(),
                         text    = "Proszę czekać kilka minut, podczas gdy zbieram dane o wybranym Hubie")

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

  # Usuwamy wiadomość informującą, że należy czekać
  bot$deleteMessage(update$from_chat_id(), mid$message_id) 

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

  # Tworzymy klawiaturę
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

  # Wysyłamy informacje o pogodzie
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = paste0("5 najnowszych artykułów z Habu ", hub),
                  reply_markup = IKM)

}

# Tworzymy filtry
## wiadomości z tekstem Pogoda
MessageFilters$hubs <- BaseFilter(function(message) {

  # Sprawdzamy tekst wiadomości
  message$text == "Lista artykułów"

}
)

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

# Dodajemy obsługiwacze do menedżera
updater <- updater + 
  h_start +
  h_hubs  +
  h_query_handler

# Uruchamiamy bota
updater$start_polling()

Uruchom powyższy przykład kodu, wcześniej zastępując ‘TWÓJ TOKEN BOTA’ prawdziwym tokenem, który otrzymałeś podczas tworzenia bota przez BotFather (o tworzeniu bota opowiadałem w pierwszym artykule).

W rezultacie uzyskamy taki efekt:
Tworzymy bota Telegram w języku R (część 3): Jak dodać wsparcie dla klawiatury do bota

Listę dostępnych do wyboru Hublów wprowadziliśmy na sztywno w metodzie 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)
}

Listę artykułów z podanego Hublu otrzymujemy za pomocą komendy habr_hub_posts(), z pakietu habR. Przy tym wskazujemy, że nie potrzebujemy listy artykułów za cały czas, a jedynie pierwszej strony, na której znajduje się 20 artykułów. Z uzyskanej tabeli za pomocą komendy head() zostawiamy tylko 5 najwyższych, które są najnowszymi artykułami.

  # парсим Хабр
  posts <- head(habr_hub_posts(hub, 1), 5)

Logika jest bardzo podobna do poprzedniego bota, ale w tym przypadku inline klawiaturę ze listą artykułów generujemy dynamicznie za pomocą funkcji lapply().

  # формируем список кнопок
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  # формируем клавиатуру
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

Do tekstu przycisku podstawiamy tytuł artykułu posts$title[x], a w argument url link do artykułu: url = posts$link[x].

Następnie tworzymy filtr, obsługiwacze i uruchamiamy naszego bota.

Podsumowanie

Teraz napisane przez Ciebie boty będą znacznie wygodniejsze w użytkowaniu, ponieważ zarządzanie nimi odbywać się będzie za pomocą klawiatury, a nie poprzez wprowadzanie komend. Przynajmniej przy interakcji z botem za pomocą smartfona klawiatura znacznie uprości proces użytkowania.

W następnym artykule rozwiążemy, jak budować logiczny dialog z botem i pracować z bazami danych.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster