ProHoster > Блог > Kev tswj hwm > Sau ib lub telegram bot hauv R (ib ntu 4): Tsim kom muaj kev sib raug zoo, kev sib tham nrog tus bot
Sau ib lub telegram bot hauv R (ib ntu 4): Tsim kom muaj kev sib raug zoo, kev sib tham nrog tus bot
Yog koj twb tau nyeem yav dhau los lawm peb tsab xov xwm los ntawm no series, ces koj twb paub yuav ua li cas sau tag nrho-fledged telegram bots nrog ib tug keyboard.
Hauv tsab xov xwm no, peb yuav kawm yuav ua li cas sau ib tus bot uas yuav tswj tau qhov kev sib tham zoo ib yam. Cov. bot yuav nug koj cov lus nug thiab tos koj nkag mus rau qee cov ntaub ntawv. Nyob ntawm cov ntaub ntawv koj nkag mus, bot yuav ua qee yam haujlwm.
Tsis tas li hauv tsab xov xwm no peb yuav kawm paub siv cov ntaub ntawv hauv qab hood ntawm bot, hauv peb qhov piv txwv nws yuav yog SQLite, tab sis koj tuaj yeem siv lwm yam DBMS. Kuv tau sau kom ntxaws ntxiv txog kev cuam tshuam nrog cov ntaub ntawv hauv R hom lus hauv qhov no tsab xov xwm.
Tag nrho cov ntawv los ntawm koob "Sau ib lub xov tooj bot hauv R"
Txhawm rau kom bot thov cov ntaub ntawv los ntawm koj thiab tos kom koj nkag mus rau txhua yam ntaub ntawv, koj yuav tsum tau sau lub xeev tam sim no ntawm kev sib tham. Txoj hauv kev zoo tshaj los ua qhov no yog siv qee yam ntawm cov ntaub ntawv embedded, xws li SQLite.
Cov. Lub logic yuav ua raws li nram no. Peb hu rau txoj kev bot, thiab bot tau thov qee cov ntaub ntawv los ntawm peb, thiab ntawm txhua kauj ruam nws tos cov ntaub ntawv no nkag mus thiab tuaj yeem tshawb xyuas nws.
Peb yuav sau qhov yooj yim tshaj plaws ua tau bot, ua ntej nws yuav nug koj lub npe, tom qab ntawd koj lub hnub nyoog, thiab yuav khaws cov ntaub ntawv tau txais mus rau hauv cov ntaub ntawv. Thaum nug txog hnub nyoog, nws yuav xyuas tias cov ntaub ntawv nkag yog tus lej thiab tsis yog ntawv.
Xws li kev sib tham yooj yim yuav muaj tsuas yog peb lub xeev:
pib yog lub xeev ib txwm ntawm bot, uas nws tsis cia siab tias yuav muaj cov ntaub ntawv los ntawm koj
wait_name - lub xeev uas tus bot tos rau lub npe nkag
wait_age yog lub xeev uas tus bot tos koj lub hnub nyoog nkag, tus naj npawb ntawm xyoo.
Koj tuaj yeem tsim lossis kho cov ntaub ntawv no siv cov lus txib file.edit(path.expand(file.path("~", ".Renviron"))). Ua nws thiab ntxiv ib kab rau hauv cov ntaub ntawv:
TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ
Tom ntej no txuag cov ntaub ntawv .Renviron thiab rov pib RStudio.
Tsim ib tug database
Cov kauj ruam tom ntej yog los tsim ib lub database. Peb yuav xav tau 2 lub rooj:
chat_data - cov ntaub ntawv uas tus bot thov los ntawm tus neeg siv
chat_state - lub xeev tam sim no ntawm txhua qhov kev sib tham
Koj tuaj yeem tsim cov ntxhuav no siv cov lus nug SQL nram qab no:
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
);
Yog tias koj rub tawm qhov project bot los ntawm GitHub, tom qab ntawd los tsim cov ntaub ntawv koj tuaj yeem siv cov cai hauv qab no hauv 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'))
Sau cov haujlwm ua haujlwm nrog cov ntaub ntawv
Peb twb muaj ib tug configuration ntaub ntawv npaj thiab ib tug database tsim. Tam sim no koj yuav tsum sau cov haujlwm los nyeem thiab sau cov ntaub ntawv rau hauv cov ntaub ntawv no.
# ###########################################################
# 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]])
}
Peb tsim 4 txoj haujlwm yooj yim:
get_state() - tau txais lub xeev sib tham tam sim no los ntawm database
set_state() - sau lub xeev kev sib tham tam sim no rau hauv database
get_chat_data() - tau txais cov ntaub ntawv xa los ntawm tus neeg siv
set_chat_data() - sau cov ntaub ntawv tau txais los ntawm tus neeg siv
Tag nrho cov haujlwm yog qhov yooj yim heev, lawv yog nyeem cov ntaub ntawv los ntawm cov ntaub ntawv siv cov lus txib dbGetQuery(), los yog cog lus UPSERT kev ua haujlwm (hloov cov ntaub ntawv uas twb muaj lawm lossis sau cov ntaub ntawv tshiab rau hauv cov ntaub ntawv), siv cov haujlwm dbExecute().
Cov syntax rau UPSERT kev ua haujlwm yog raws li hauv qab no:
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
Cov. hauv peb lub rooj teb chat_id muaj ib tug uniqueness txwv thiab yog lub ntsiab tseem ceeb ntawm cov ntxhuav. Thaum pib, peb sim ntxiv cov ntaub ntawv rau lub rooj, thiab peb tau txais qhov yuam kev yog tias cov ntaub ntawv rau kev sib tham tam sim no twb muaj lawm, qhov twg peb tsuas hloov kho cov ntaub ntawv rau kev sib tham no.
Tom ntej no, peb yuav siv cov haujlwm no hauv bot txoj kev thiab cov lim dej.
Cov txheej txheem bot
Cov kauj ruam tom ntej hauv kev tsim peb bot yog los tsim cov txheej txheem. Yog hais tias koj downloaded qhov project los ntawm GitHub, ces txhua txoj kev yog nyob rau hauv cov ntaub ntawv bot_methods.R.
Bot txoj kev code
# ###########################################################
# 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')
}
}
Peb tsim 5 txoj kev:
pib - Pib lub dialog
xeev - Tau txais lub xeev sib tham tam sim no
rov pib dua - Rov pib dua lub xeev kev sib tham tam sim no
enter_name - Tus bot nug koj lub npe
enter_age - Tus bot nug koj lub hnub nyoog
Txujci start nug koj lub npe, thiab hloov lub xeev kev sib tham rau tos_npe, i.e. mus standby rau sau koj lub npe.
Tom ntej no, koj xa lub npe thiab nws yog ua tiav los ntawm txoj kev enter_name, bot txais tos koj, sau lub npe tau txais rau hauv cov ntaub ntawv, thiab hloov cov kev sib tham mus rau lub xeev tos_age.
Nyob rau theem no, bot xav kom koj nkag mus rau koj lub hnub nyoog. Koj xa koj lub hnub nyoog, bot tshawb xyuas cov lus, yog tias koj xa qee cov ntawv tsis yog tus lej, nws yuav hais tias: Ты ввёл некорректные данные, введи число, thiab yuav tos kom koj rov nkag koj cov ntaub ntawv. Yog tias koj xa tus lej, bot yuav tshaj tawm tias nws tau txais koj lub hnub nyoog, sau cov ntaub ntawv tau txais mus rau hauv cov ntaub ntawv, tshaj tawm tag nrho cov ntaub ntawv tau txais los ntawm koj thiab xa rov qab lub xeev kev sib tham mus rau nws txoj haujlwm qub, i.e. V start.
Los ntawm kev hu rau txoj kev state koj tuaj yeem thov qhov kev sib tham tam sim no txhua lub sijhawm, thiab siv lub reset rov qab sib tham mus rau nws lub xeev qub.
Cov lus lim
Hauv peb qhov xwm txheej, qhov no yog ib qho tseem ceeb tshaj plaws hauv kev tsim lub bot. Nws yog nrog kev pab los ntawm cov lus lim uas bot yuav nkag siab txog cov ntaub ntawv nws xav tau los ntawm koj thiab yuav ua li cas nws yuav tsum tau ua.
Hauv qhov project ntawm GitHub cov ntxaij lim dej tau sau npe rau hauv cov ntaub ntawv message_filters.R.
Message filter code:
# ###########################################################
# 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"
}
)
Hauv cov ntxaij lim dej peb siv cov haujlwm sau yav dhau los get_state(), txhawm rau thov lub xeev tam sim no ntawm kev sib tham. Txoj haujlwm no tsuas yog 1 qhov kev sib cav, sib tham id.
Tom ntej no lim tos_npe ua cov lus thaum sib tham nyob rau hauv ib lub xeev wait_name, thiab raws li cov lim tos_age ua cov lus thaum sib tham nyob rau hauv ib lub xeev wait_age.
Cov tuav
Cov ntaub ntawv nrog tus tuav yog hu ua cov kws kho mob.R, thiab muaj cov cai hauv qab no:
# ###########################################################
# 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)
Ua ntej peb tsim cov neeg tuav cov lus txib uas yuav tso cai rau koj los khiav txoj hauv kev los pib sib tham, rov pib dua, thiab nug txog lub xeev tam sim no.
Tam sim no peb muaj txhua yam npaj txhij mus tso tawm, lub ntsiab cai rau launching bot yog nyob rau hauv cov ntaub ntawv 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()
Yog li ntawd, peb tau txais no bot:
Thaum twg los tau siv cov lus txib /state peb tuaj yeem nug lub xeev kev sib tham tam sim no, thiab siv cov lus txib /reset rov qab sib tham mus rau nws lub xeev qub thiab pib qhov kev sib tham dua.
xaus
Hauv tsab xov xwm no, peb xav txog yuav ua li cas siv cov ntaub ntawv hauv ib lub bot, thiab yuav ua li cas los tsim cov kev sib tham sib txuas lus los ntawm kev sau cov lus sib tham.
Hauv qhov no, peb tau saib cov piv txwv tseem ceeb tshaj plaws, yog li ntawd nws yuav yooj yim dua rau koj kom nkag siab txog lub tswv yim ntawm kev tsim cov bots; hauv kev xyaum, koj tuaj yeem tsim ntau cov kev sib tham nyuaj.
Nyob rau hauv tsab xov xwm tom ntej no, peb yuav kawm yuav ua li cas txwv txoj cai ntawm cov neeg siv bot siv ntau yam ntawm nws txoj kev.