Jika Anda sudah membaca tiga artikel sebelumnya di seri ini, maka Anda sudah tahu cara menulis bot telegram lengkap dengan keyboard.
Pada artikel ini, kita akan belajar bagaimana menulis bot yang akan menjaga dialog yang konsisten. Itu. bot akan mengajukan pertanyaan kepada Anda dan menunggu Anda memasukkan informasi apa pun. Bergantung pada data yang Anda masukkan, bot akan melakukan beberapa tindakan.
Juga di artikel ini kita akan belajar bagaimana menggunakan database di bawah tenda bot, dalam contoh kita itu adalah SQLite, tetapi Anda dapat menggunakan DBMS lainnya. Saya menulis lebih detail tentang berinteraksi dengan database dalam bahasa R di artikel ini .

Semua artikel dari seri "Menulis bot telegram dalam bahasa R"
- Kami membuat bot dan mengirim pesan ke telegram menggunakannya
- Tambahkan dukungan perintah dan filter pesan ke bot
- Cara menambahkan dukungan keyboard ke bot Anda
- Membangun dialog yang konsisten dan logis dengan bot
- Manajemen hak pengguna bot
Kandungan
, , - . , , SQLite.
.. . , - , , .
, , , . , , .
:
- start — ,
- wait_name — ,
- wait_age — , , .
, :

- , . , .
- , .
- , , .
- , .. .
- . , .
- , .
- .
, .
- bot.R —
- db_bot_function.R —
- bot_methods.R —
- message_filters.R —
- handlers.R —
- config.cfg —
- create_db_data.sql — SQL
- create_db_state.sql — SQL
- bot.db —
, GitHub.
ini , :
[bot_settings]
bot_token=__
[db_settings]
db_path=C://///bot.db
, , .. bot.db, .
, ini , JSON.
, , TG_BOT_PATH.
, — .Renviron.
, file.edit(path.expand(file.path("~", ".Renviron"))). :
TG_BOT_PATH=C:////
.Renviron RStudio.
— . 2 :
- chat_data —
- chat_state —
SQL :
CREATE TABLE chat_data (
chat_id BIGINT PRIMARY KEY
UNIQUE,
name TEXT,
age INTEGER
);
CREATE TABLE chat_state (
chat_id BIGINT PRIMARY KEY
UNIQUE,
state TEXT
);
GitHub, R.
#
library(DBI) #
library(configr) #
library(readr) # SQL
library(RSQLite) # SQLite
#
setwd(Sys.getenv('TG_BOT_PATH'))
#
cfg <- read.config('config.cfg')
# SQLite
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
#
dbExecute(con, statement = read_file('create_db_data.sql'))
dbExecute(con, statement = read_file('create_db_state.sql'))
. .
GitHub, db_bot_function.R.
# ###########################################################
# Function for work bot with database
#
get_state <- function(chat_id) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
chat_state <- dbGetQuery(con, str_interp("SELECT state FROM chat_state WHERE chat_id == ${chat_id}"))$state
return(unlist(chat_state))
dbDisconnect(con)
}
#
set_state <- function(chat_id, state) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert
dbExecute(con,
str_interp("
INSERT INTO chat_state (chat_id, state)
VALUES(${chat_id}, '${state}')
ON CONFLICT(chat_id)
DO UPDATE SET state='${state}';
")
)
dbDisconnect(con)
}
#
set_chat_data <- function(chat_id, field, value) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert
dbExecute(con,
str_interp("
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
")
)
dbDisconnect(con)
}
# read chat data
get_chat_data <- function(chat_id, field) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert
data <- dbGetQuery(con,
str_interp("
SELECT ${field}
FROM chat_data
WHERE chat_id = ${chat_id};
")
)
dbDisconnect(con)
return(data[[field]])
}4 :
get_state()—set_state()—get_chat_data()—set_chat_data()—
, dbGetQuery(), UPSERT ( ), dbExecute().
UPSERT :
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
.. chat_id . , , .
.
. GitHub, bot_methods.R.
# ###########################################################
# bot methods
# start dialog
start <- function(bot, update) {
#
# Send query
bot$sendMessage(update$message$chat_id,
text = " ")
#
set_state(chat_id = update$message$chat_id, state = 'wait_name')
}
# get current chat state
state <- function(bot, update) {
chat_state <- get_state(update$message$chat_id)
# Send state
bot$sendMessage(update$message$chat_id,
text = unlist(chat_state))
}
# reset dialog state
reset <- function(bot, update) {
set_state(chat_id = update$message$chat_id, state = 'start')
}
# enter username
enter_name <- function(bot, update) {
uname <- update$message$text
# Send message with name
bot$sendMessage(update$message$chat_id,
text = paste0(uname, ", , !"))
#
#username <<- uname
set_chat_data(update$message$chat_id, 'name', uname)
#
bot$sendMessage(update$message$chat_id,
text = " ?")
#
set_state(chat_id = update$message$chat_id, state = 'wait_age')
}
# enter user age
enter_age <- function(bot, update) {
uage <- as.numeric(update$message$text)
#
if ( is.na(uage) ) {
#
bot$sendMessage(update$message$chat_id,
text = " , ")
} else {
#
bot$sendMessage(update$message$chat_id,
text = ", ")
#
#userage <<- uage
set_chat_data(update$message$chat_id, 'age', uage)
#
username <- get_chat_data(update$message$chat_id, 'name')
userage <- get_chat_data(update$message$chat_id, 'age')
bot$sendMessage(update$message$chat_id,
text = paste0(" ", username, " ", userage, " . "))
#
set_state(chat_id = update$message$chat_id, state = 'start')
}
}5 :
- start —
- state —
- reset —
- enter_name —
- enter_age —
start , wait_name, .. .
, enter_name, , , wait_age.
. , , - : , , . , , , , , .. start.
state , reset .
. , .
GitHub message_filters.R.
:
# ###########################################################
# message state filters
#
MessageFilters$wait_name <- BaseFilter(function(message) {
get_state( message$chat_id ) == "wait_name"
}
)
#
MessageFilters$wait_age <- BaseFilter(function(message) {
get_state( message$chat_id ) == "wait_age"
}
)
get_state(), , . 1 , id .
wait_name wait_name, wait_age wait_age.
handlers.R, :
# ###########################################################
# handlers
# command handlers
start_h <- CommandHandler('start', start)
state_h <- CommandHandler('state', state)
reset_h <- CommandHandler('reset', reset)
# message handlers
## !MessageFilters$command - ,
##
wait_age_h <- MessageHandler(enter_age, MessageFilters$wait_age & !MessageFilters$command)
wait_name_h <- MessageHandler(enter_name, MessageFilters$wait_name & !MessageFilters$command)
, , , .
2 , !MessageFilters$command, , .
, bot.R.
library(telegram.bot)
library(tidyverse)
library(RSQLite)
library(DBI)
library(configr)
#
setwd(Sys.getenv('TG_BOT_PATH'))
#
cfg <- read.config('config.cfg')
#
updater <- Updater(cfg$bot_settings$bot_token)
#
source('db_bot_function.R') #
source('bot_methods.R') #
source('message_filters.R') #
source('handlers.R') #
#
updater <- updater +
start_h +
wait_age_h +
wait_name_h +
state_h +
reset_h
#
updater$start_polling()
, :

/state , /reset .
, .
Dalam hal ini, kami memeriksa contoh paling primitif, untuk memudahkan Anda memahami ide membangun bot semacam itu, dalam praktiknya Anda dapat membuat dialog yang jauh lebih kompleks.
Pada artikel berikutnya dalam seri ini, kita akan mempelajari cara membatasi hak pengguna bot untuk menggunakan berbagai metode.