ProHoster > Blog > Stjórnsýsla > Að skrifa símskeyti botni í R (hluti 4): Byggja upp samkvæma, rökrétta samræður við botninn
Að skrifa símskeyti botni í R (hluti 4): Byggja upp samkvæma, rökrétta samræður við botninn
Ef þú hefur þegar lesið fyrri þrjár greinar úr þessari seríu, þá veistu nú þegar hvernig á að skrifa fullgilda símskeyti vélmenni með lyklaborði.
Í þessari grein munum við læra hvernig á að skrifa vélmenni sem mun viðhalda stöðugri umræðu. Þeir. Botninn mun spyrja þig spurninga og bíða eftir að þú slærð inn einhverjar upplýsingar. Það fer eftir gögnunum sem þú slærð inn, botninn mun framkvæma nokkrar aðgerðir.
Einnig í þessari grein munum við læra hvernig á að nota gagnagrunn undir hettunni á botni, í okkar dæmi mun það vera SQLite, en þú getur notað hvaða önnur DBMS sem er. Ég skrifaði nánar um samskipti við gagnagrunna á R tungumálinu í Þessi grein.
Allar greinar úr seríunni „Að skrifa símskeyti láni í R“
Til þess að botninn geti beðið um gögn frá þér og bíð eftir að þú slærð inn einhverjar upplýsingar þarftu að skrá núverandi stöðu samræðunnar. Besta leiðin til að gera þetta er að nota einhvers konar innbyggðan gagnagrunn, eins og SQLite.
Þeir. Rökfræðin verður sem hér segir. Við köllum botnaaðferðina og botninn biður í röð um einhverjar upplýsingar frá okkur og í hverju skrefi bíður hann eftir að þessar upplýsingar séu færðar inn og getur athugað þær.
Við munum skrifa einfaldasta mögulega vélmenni, fyrst mun það biðja um nafnið þitt, síðan aldur þinn, og mun vista móttekin gögn í gagnagrunninum. Þegar spurt er um aldur mun það athuga hvort innslögðu gögnin séu númer en ekki texti.
Slík einföld samræða mun aðeins hafa þrjú ríki:
byrjun er eðlilegt ástand vélmennisins, þar sem það býst ekki við neinum upplýsingum frá þér
wait_name - ástand þar sem botni bíður eftir að nafn sé slegið inn
wait_age er ástandið þar sem botninn bíður eftir að aldur þinn sé færður inn, fjöldi heilra ára.
Bot byggingarferli
Meðan á greininni stendur munum við búa til vélmenni skref fyrir skref; allt ferlið er hægt að sýna með skýringarmynd sem hér segir:
Við búum til bot config þar sem við munum geyma nokkrar stillingar. Í okkar tilviki, botn táknið og slóðin að gagnagrunnsskránni.
Við búum til umhverfisbreytu þar sem leiðin að verkefninu með botni verður geymd.
Við búum til gagnagrunninn sjálfan og fjölda aðgerða svo að botninn geti haft samskipti við hann.
Við skrifum bot aðferðir, þ.e. aðgerðir sem það mun framkvæma.
Bætir við skilaboðasíum. Með hjálp sem lánmaðurinn mun fá aðgang að nauðsynlegum aðferðum, allt eftir núverandi stöðu spjallsins.
Við bætum við meðhöndlum sem munu tengja skipanir og skilaboð með nauðsynlegum botnaaðferðum.
Við skulum ræsa botann.
Bot verkefni uppbygging
Til hægðarauka munum við skipta kóðanum á botni okkar, og öðrum tengdum skrám, í eftirfarandi uppbyggingu.
bot.R - aðalkóði láni okkar
db_bot_function.R — kóðablokk með aðgerðum til að vinna með gagnagrunn
bot_methods.R — kóða lánaaðferða
skilaboðasíur.R — skilaboðasíur
umsjónarmenn.R - umsjónarmenn
config.cfg - bot config
búa til_db_gögn.sql — SQL forskrift til að búa til töflu með spjallgögnum í gagnagrunninum
búa til_db_state.sql — SQL forskrift til að búa til töflu yfir núverandi spjallástand í gagnagrunninum
Í stillingunni skrifum við bot token og slóðina að gagnagrunninum, þ.e. í bot.db skrána; við munum búa til skrána sjálfa í næsta skrefi.
Fyrir flóknari vélmenni geturðu búið til flóknari stillingar, auk þess er ekki nauðsynlegt að skrifa ini stillingar, þú getur notað hvaða annað snið sem er, þar á meðal JSON.
Búðu til umhverfisbreytu
Á hverri tölvu getur möppan með bot-verkefninu verið staðsett í mismunandi möppum og á mismunandi drifum, þannig að í kóðanum verður slóðin að verkefnamöppunni stillt með umhverfisbreytu TG_BOT_PATH.
Það eru nokkrar leiðir til að búa til umhverfisbreytu, einfaldast er að skrifa hana í skrá .Environ.
Þú getur búið til eða breytt þessari skrá með skipuninni file.edit(path.expand(file.path("~", ".Renviron"))). Keyrðu það og bættu einni línu við skrána:
TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ
Næst skaltu vista skrána .Environ og endurræstu RStudio.
Að búa til gagnagrunn
Næsta skref er að búa til gagnagrunn. Við þurfum 2 borð:
chat_data — gögn sem botninn bað um frá notandanum
chat_state — núverandi ástand allra spjalla
Þú getur búið til þessar töflur með því að nota eftirfarandi SQL fyrirspurn:
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
);
Ef þú halaðir niður botaverkefninu frá GitHub, til að búa til gagnagrunninn geturðu notað eftirfarandi kóða í 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'))
Ritunaraðgerðir til að vinna með gagnagrunninn
Við erum nú þegar með stillingarskrá tilbúin og gagnagrunn búinn til. Nú þarftu að skrifa aðgerðir til að lesa og skrifa gögn í þennan gagnagrunn.
Ef þú hefur hlaðið niður verkefninu frá GitHub, þá geturðu fundið aðgerðirnar í skránni db_bot_function.R.
Aðgerðarkóði til að vinna með gagnagrunninn
# ###########################################################
# 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]])
}
Við bjuggum til 4 einfaldar aðgerðir:
get_state() — fáðu núverandi spjallstöðu úr gagnagrunninum
set_state() — skrifaðu núverandi spjallástand í gagnagrunninn
get_chat_data() — taka á móti gögnum sem notandinn sendir
set_chat_data() — skrá gögn sem berast frá notanda
Allar aðgerðir eru frekar einfaldar, þær lesa ýmist gögn úr gagnagrunninum með skipuninni dbGetQuery(), eða skuldbinda sig UPSERT aðgerð (að breyta fyrirliggjandi gögnum eða skrifa ný gögn í gagnagrunninn), með því að nota aðgerðina dbExecute().
Setningafræði fyrir UPSERT aðgerðina er sem hér segir:
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
Þeir. í töflureitnum okkar spjall_id hefur sérstöðuþvingun og er aðallykill töflur. Upphaflega reynum við að bæta upplýsingum við töfluna og við fáum villu ef gögn fyrir núverandi spjall eru þegar til staðar, í því tilviki uppfærum við einfaldlega upplýsingarnar fyrir þetta spjall.
Næst munum við nota þessar aðgerðir í aðferðum og síum vélmennisins.
Bot aðferðir
Næsta skref í að byggja upp vélmenni okkar er að búa til aðferðir. Ef þú hefur hlaðið niður verkefninu frá GitHub, þá eru allar aðferðir í skránni bot_methods.R.
Bot aðferð kóði
# ###########################################################
# 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')
}
}
Við bjuggum til 5 aðferðir:
byrja — Byrjaðu glugga
ástand — Fáðu núverandi spjallstöðu
endurstilla — Núllstilla núverandi spjallástand
enter_name — Botninn biður um nafnið þitt
enter_age — Botninn spyr um aldur þinn
Aðferð start biður um nafnið þitt og breytir spjallstöðu í bið_nafn, þ.e. í biðstöðu til að slá inn nafnið þitt.
Næst sendir þú nafnið og það er unnið með aðferðinni enter_name, botninn heilsar þér, skrifar móttekið nafn inn í gagnagrunninn og skiptir spjallinu yfir í ástandið bið_aldur.
Á þessu stigi býst vélmaðurinn við að þú slærð inn aldur þinn. Þú sendir aldur þinn, botninn athugar skilaboðin, ef þú sendir smá texta í stað númers mun hann segja: Ты ввёл некорректные данные, введи число, og mun bíða eftir að þú slærð inn gögnin þín aftur. Ef þú sendir númer mun botninn tilkynna að hann hafi samþykkt aldur þinn, skrifa móttekin gögn í gagnagrunninn, tilkynna öll gögn sem berast frá þér og skila spjallástandi í upprunalega stöðu, þ.e. V start.
Með því að kalla aðferðina state þú getur beðið um núverandi spjallstöðu hvenær sem er og með því að nota reset koma spjallinu í upprunalegt horf.
Skilaboðasíur
Í okkar tilviki er þetta einn mikilvægasti hlutinn við að byggja upp vélmenni. Það er með hjálp skilaboðasíur sem botninn mun skilja hvaða upplýsingar hann býst við frá þér og hvernig ætti að vinna úr þeim.
Í verkefninu á GitHub síur eru skráðar í skrána skilaboðasíur.R.
Skilaboðasíukóði:
# ###########################################################
# 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"
}
)
Í síum notum við áður skrifaða aðgerðina get_state(), til að biðja um núverandi stöðu spjallsins. Þessi aðgerð krefst aðeins 1 rök, spjallauðkenni.
Næsta sía bið_nafn vinnur úr skilaboðum þegar spjallið er í ástandi wait_name, og í samræmi við síuna bið_aldur vinnur úr skilaboðum þegar spjallið er í ástandi wait_age.
Handhafar
Skráin með meðhöndlum er kölluð umsjónarmenn.R, og hefur eftirfarandi kóða:
# ###########################################################
# 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)
Fyrst búum við til skipanameðhöndlun sem gerir þér kleift að keyra aðferðir til að hefja svarglugga, endurstilla hann og spyrjast fyrir um núverandi ástand.
Næst búum við til 2 skilaboðastjóra með því að nota síurnar sem voru búnar til í fyrra skrefi og bætum síu við þá !MessageFilters$command, svo að við getum notað skipanir í hvaða spjalli sem er.
Bot ræsingarkóði
Nú höfum við allt tilbúið til að ræsa, aðalkóði til að ræsa botni er í skránni 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()
Fyrir vikið fengum við þennan bot:
Hvenær sem er með því að nota skipunina /state við getum spurt um núverandi spjallstöðu og notað skipunina /reset koma spjallinu aftur í upprunalegt horf og hefja samtalið aftur.
Ályktun
Í þessari grein komumst við að því hvernig á að nota gagnagrunn inni í vélmenni og hvernig á að byggja upp röð rökréttar samræður með því að skrá spjallástandið.
Í þessu tilviki skoðuðum við frumstæðasta dæmið, svo að það væri auðveldara fyrir þig að skilja hugmyndina um að smíða slíka vélmenni; í reynd geturðu byggt upp miklu flóknari samræður.
Í næstu grein í þessari röð munum við læra hvernig á að takmarka réttindi botnotenda til að nota ýmsar aðferðir þess.