ProHoster > Blog > Administrazioa > Telegram bot bat idaztea R-n (4. zatia): botarekin elkarrizketa koherente eta logikoa eraikitzea
Telegram bot bat idaztea R-n (4. zatia): botarekin elkarrizketa koherente eta logikoa eraikitzea
Aurrekoa irakurri baduzu dagoeneko hiru artikulu serie honetatik, badakizu dagoeneko teklatu batekin telegram bot osoak idazten.
Artikulu honetan, elkarrizketa koherentea mantenduko duen bot bat idazten ikasiko dugu. Horiek. Botak galderak egingo dizkizu eta informazio batzuk sartu arte itxarongo dizu. Sartzen dituzun datuen arabera, bot-ak ekintza batzuk egingo ditu.
Artikulu honetan ere bot-aren kaputxa azpian datu-base bat nola erabili ikasiko dugu, gure adibidean SQLite izango da, baina beste edozein DBMS erabil dezakezu. R hizkuntzan datu-baseekin elkarreragineari buruz zehatzago idatzi nuen Artikulu honetan.
"Telegram bot bat R-n idazten" serieko artikulu guztiak
Botak zuri datuak eskatzeko eta edozein informazio sartu arte itxaron ahal izateko, elkarrizketaren uneko egoera grabatu beharko duzu. Horretarako modurik onena kapsulatutako datu-baseren bat erabiltzea da, adibidez SQLite.
Horiek. Logika hau izango da. Bot metodoari deitzen diogu, eta bot-ak sekuentzialki informazio batzuk eskatzen dizkigu, eta urrats bakoitzean informazio hori sartu arte itxaroten du eta egiaztatu ahal izango du.
Ahalik eta bot errazena idatziko dugu, lehenik zure izena eskatuko du, gero zure adina, eta jasotako datuak datu-basean gordeko ditu. Adina galdetzean, sartutako datuak zenbaki bat direla eta ez testua egiaztatuko du.
Elkarrizketa sinple horrek hiru egoera baino ez ditu izango:
start bot-aren egoera normala da, eta bertan ez du zuregandik inolako informaziorik espero
wait_name - bot-ak izen bat sartu arte itxaroten duen egoera
wait_age bot-ak zure adina sartu arte itxaroten duen egoera da, urte osoen kopurua.
Bot eraikuntza prozesua
Artikuluan zehar, bot bat eraikiko dugu urratsez urrats; prozesu osoa eskematikoki honela irudikatu daiteke:
Bot konfigurazio bat sortzen dugu eta bertan ezarpen batzuk gordeko ditugu. Gure kasuan, bot tokena eta datu-basearen fitxategirako bidea.
Ingurune-aldagai bat sortzen dugu eta bertan botarekin proiekturako bidea gordeko da.
Datu-basea bera sortzen dugu, eta hainbat funtzio, bot-ak harekin elkarreragin dezan.
Bot metodoak idazten ditugu, hau da. beteko dituen funtzioak.
Mezu-iragazkiak gehitzea. Horren laguntzaz bot-ak beharrezko metodoetara sartuko du, txataren uneko egoeraren arabera.
Komandoak eta mezuak beharrezko bot metodoekin konektatuko dituzten kudeatzaileak gehitzen ditugu.
Abiarazi dezagun bot-a.
Bot proiektuaren egitura
Erosotasunerako, gure botaren kodea eta erlazionatutako beste fitxategi batzuk hurrengo egituran banatuko ditugu.
bot.R - gure bot-aren kode nagusia
db_bot_function.R — datu-basearekin lan egiteko funtzioak dituen kode bloke bat
bot_metodoak.R — bot metodoen kodea
mezu_iragazkiak.R — mezuen iragazkiak
kudeatzaileak.R - kudeatzaileak
konfig.cfg - bot konfigurazioa
create_db_data.sql — Datu-basean txat-datuekin taula bat sortzeko SQL scripta
create_db_state.sql — Datu-basean uneko txat egoeraren taula bat sortzeko SQL scripta
Konfigurazioan bot tokena eta datu-baserako bidea idazten ditugu, hau da. bot.db fitxategira; fitxategia bera sortuko dugu hurrengo urratsean.
Bot konplexuagoetarako, konfigurazio konplexuagoak sor ditzakezu, gainera, ez da beharrezkoa ini konfigurazioa idaztea, beste edozein formatu erabil dezakezu JSON barne.
Sortu ingurune-aldagai bat
PC bakoitzean, bot proiektua duen karpeta direktorio ezberdinetan eta disko ezberdinetan egon daiteke, beraz, kodean proiektuaren karpetarako bidea ingurune-aldagai baten bidez ezarriko da. TG_BOT_PATH.
Ingurune aldagai bat sortzeko hainbat modu daude, errazena fitxategi batean idaztea da .Inguruan.
Komandoa erabiliz fitxategi hau sortu edo edita dezakezu file.edit(path.expand(file.path("~", ".Renviron"))). Exekutatu eta gehitu lerro bat fitxategiari:
TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ
Ondoren, gorde fitxategia .Inguruan eta berrabiarazi RStudio.
Datu-base bat sortzea
Hurrengo urratsa datu-base bat sortzea da. 2 taula beharko ditugu:
chat_data - bot-ak erabiltzaileari eskatutako datuak
chat_state — txat guztien egungo egoera
Taula hauek sor ditzakezu SQL kontsulta hau erabiliz:
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
);
Bot proiektua deskargatu baduzu GitHub, ondoren datu-basea sortzeko hurrengo kodea erabil dezakezu R-n.
# Скрипт создания базы данных
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'))
Datu-basearekin lan egiteko funtzioak idaztea
Dagoeneko prest daukagu konfigurazio fitxategi bat eta datu-base bat sortua. Orain datu-base honetan datuak irakurtzeko eta idazteko funtzioak idatzi behar dituzu.
Proiektua hemendik deskargatu baduzu GitHub, orduan funtzioak fitxategian aurki ditzakezu db_bot_function.R.
Datu-basearekin lan egiteko funtzio-kodea
# ###########################################################
# 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 funtzio sinple sortu ditugu:
get_state() — eskuratu uneko txat-egoera datu-basetik
set_state() — idatzi uneko txat-egoera datu-basean
get_chat_data() — Erabiltzaileak bidalitako datuak jaso
set_chat_data() — erabiltzailearengandik jasotako datuak erregistratzea
Funtzio guztiak nahiko sinpleak dira, komandoa erabiliz datu-baseko datuak irakurtzen dituzte dbGetQuery(), edo konpromisoa hartu UPSERT eragiketa (dauden datuak aldatzea edo datu-basean datu berriak idaztea), funtzioa erabiliz dbExecute().
UPSERT eragiketaren sintaxia honako hau da:
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
Horiek. gure taulen eremuan txat_id berezitasun-murriztapena du eta taulen gako nagusia da. Hasieran, taulan informazioa gehitzen saiatzen gara, eta errore bat jasoko dugu uneko txataren datuak dagoeneko badaude, eta kasu horretan, berriketa honen informazioa eguneratzen dugu.
Ondoren, funtzio hauek bot-en metodo eta iragazkietan erabiliko ditugu.
Bot metodoak
Gure bot eraikitzeko hurrengo urratsa metodoak sortzea da. Proiektua hemendik deskargatu baduzu GitHub, orduan metodo guztiak fitxategian daude bot_metodoak.R.
Bot metodoaren kodea
# ###########################################################
# 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 metodo sortu ditugu:
start — Hasi elkarrizketa-koadroa
egoera — Lortu uneko txat egoera
berrezarri — Berrezarri uneko txat-egoera
enter_name — Botak zure izena eskatzen dizu
enter_age — Botak zure adina eskatzen dizu
Метод start zure izena eskatzen du, eta txat-egoera aldatzen du itxaron_izena, hau da. zure izena idazteko egonean egoteko.
Ondoren, izena bidaltzen duzu eta metodoaren bidez prozesatzen da enter_name, bot-ak agurtzen zaitu, jasotako izena datu-basean idazten du eta txata egoerara aldatzen du itxaron_adina.
Fase honetan, bot-ak zure adina sartzea espero du. Zure adina bidaltzen duzu, bot-ak mezua egiaztatzen du, zenbaki baten ordez testuren bat bidali baduzu, esango du: Ты ввёл некорректные данные, введи число, eta zure datuak berriro sartu arte itxarongo du. Zenbaki bat bidali baduzu, bot-ak zure adina onartu duela jakinaraziko du, jasotako datuak datu-basean idatziko ditu, zuregandik jasotako datu guztien berri emango du eta txat-egoera jatorrizko posiziora itzuliko du, hau da. V start.
Metodoari deituz state uneko txataren egoera edozein unetan eska dezakezu eta hau erabiliz reset itzuli txata jatorrizko egoerara.
Mezu-iragazkiak
Gure kasuan, hau da bot bat eraikitzeko zati garrantzitsuenetako bat. Mezu-iragazkien laguntzaz ulertuko du bot-ak zuregandik zer informazio espero duen eta nola prozesatu behar den.
On proiektuan GitHub iragazkiak fitxategian erregistratzen dira mezu_iragazkiak.R.
Mezuen iragazkien kodea:
# ###########################################################
# 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"
}
)
Iragazkietan aurretik idatzitako funtzioa erabiltzen dugu get_state(), txataren egungo egoera eskatzeko. Funtzio honek argumentu bakarra behar du, txataren IDa.
Hurrengo iragazkia itxaron_izena mezuak prozesatzen ditu txata egoera batean dagoenean wait_name, eta horren arabera iragazkia itxaron_adina mezuak prozesatzen ditu txata egoera batean dagoenean wait_age.
Kudeatzaileak
Kudeatzaileak dituen fitxategiari deitzen zaio kudeatzaileak.R, eta kode hau dauka:
# ###########################################################
# 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)
Lehenik eta behin, komando-kudeatzaileak sortuko ditugu, elkarrizketa-koadro bat hasteko, berrezartzeko eta uneko egoera kontsultatzeko metodoak exekutatzeko aukera emango dizutenak.
Jarraian, 2 mezu-kudeatzaile sortzen ditugu aurreko urratsean sortutako iragazkiak erabiliz, eta iragazki bat gehitzen diegu !MessageFilters$command, komandoak edozein txat egoeratan erabili ahal izateko.
Bot abiarazteko kodea
Orain dena prest dugu abiarazteko, bot-a abiarazteko kode nagusia fitxategian dago 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()
Ondorioz, bot hau lortu dugu:
Edozein unetan komandoa erabiliz /state uneko txat-egoera kontsultatu dezakegu, eta komandoa erabiliz /reset itzuli txata jatorrizko egoerara eta hasi elkarrizketa berriro.
Ondorioa
Artikulu honetan, bot baten barruan datu-base bat nola erabili eta elkarrizketa logiko sekuentzialak nola eraiki txat-egoera grabatuz asmatu dugu.
Kasu honetan, adibiderik primitiboena aztertu dugu, horrela errazagoa izango zaizu ulertzea horrelako bot-ak eraikitzeko ideia; praktikan, askoz elkarrizketa konplexuagoak eraiki ditzakezu.
Serie honetako hurrengo artikuluan, bot erabiltzaileek bere metodo desberdinak erabiltzeko eskubideak nola mugatu ikasiko dugu.